card-mod-email 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3719c8ba807c0372733ecd09c9eb2e1a635f4ad07f3558392f78525e8e91f86e
4
+ data.tar.gz: c56306768a9067cae84f5448c729dbb5e061024611eccadef71422c4ad2a6dbc
5
+ SHA512:
6
+ metadata.gz: a0637a78d1c7a46886847a66e4e38f72d92871377aa5196eabd0c77eed76575e9016ffe9f4bd4b77e32c29744a8ff64d3655a96caad5f820568a325ef918d64d
7
+ data.tar.gz: 14a8fec3f37d261f4e591de75e24988c9c894880c5f4e08362b0a386e95428730ed35c4bead808e2baa17f25f0d692c94418a2f789251a7fd6a2c154796a161b
@@ -0,0 +1,14 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ class Card
4
+ class Format
5
+ # Format text for use in html email messages
6
+ class EmailHtmlFormat < Card::Format::HtmlFormat
7
+ @@aliases["email"] = "email_html"
8
+
9
+ def self.view_caching?
10
+ false
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ class Card
4
+ class Format
5
+ # Format text for use in plain text email messages
6
+ class EmailTextFormat < Card::Format::TextFormat
7
+ def chunk_list
8
+ :references
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,41 @@
1
+
2
+ format do
3
+ # turn off autodetection of uri's
4
+ def chunk_list
5
+ :references
6
+ end
7
+ end
8
+
9
+ # format :html do
10
+ # def pointer_items args
11
+ # card.item_names(context: :raw).map do |iname|
12
+ # wrap_item iname, args
13
+ # end
14
+ # end
15
+ # end#
16
+
17
+ format :email_text do
18
+ def email_addresses context
19
+ context ||= self
20
+ card.item_names(context: context.name).map do |name|
21
+ # FIXME: context is processed twice here because pointers absolutize
22
+ # item_names by default while other types can return relative names.
23
+ # That's poor default behavior and should be fixed!
24
+ name = name.to_name.absolute context
25
+ email_address?(name) ? name : email_address_from_card(name, context)
26
+ end.flatten.compact.join(", ")
27
+ end
28
+
29
+ def email_address? string
30
+ string =~ /.+\@.+\..+/
31
+ end
32
+
33
+ def email_address_from_card name, context
34
+ card = Card.fetch name
35
+ card.account&.email || email_addresses_from_card_content(card, context)
36
+ end
37
+
38
+ def email_addresses_from_card_content card, context
39
+ subformat(card).contextual_content(context).split(/[,\n]/)
40
+ end
41
+ end
@@ -0,0 +1,26 @@
1
+ format :html do
2
+ view :core do
3
+ return super() if voo.hide? :test_context
4
+ card.with_context test_context_card do
5
+ super()
6
+ end
7
+ end
8
+
9
+ def test_context_card
10
+ card.left.fetch(:test_context)&.item_card
11
+ end
12
+ end
13
+
14
+ format :email_html do
15
+ view :core do
16
+ voo.hide! :test_context
17
+ super()
18
+ end
19
+ end
20
+
21
+ format :email_text do
22
+ view :core do
23
+ voo.hide! :test_context
24
+ super()
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ format :email_html do
2
+ view :unknown do
3
+ ""
4
+ end
5
+
6
+ view :compact_missing do
7
+ ""
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+
2
+ format :email_text do
3
+ view :unknown do
4
+ ""
5
+ end
6
+
7
+ view :compact_missing do
8
+ ""
9
+ end
10
+
11
+ view :last_action, perms: :none, cache: :never do
12
+ _render_last_action_verb
13
+ end
14
+ end
@@ -0,0 +1 @@
1
+ include_set Abstract::EmailField
@@ -0,0 +1 @@
1
+ include_set Abstract::EmailField
@@ -0,0 +1 @@
1
+ include_set Abstract::EmailField
@@ -0,0 +1,13 @@
1
+ include_set Abstract::TestContext
2
+
3
+ def clean_html?
4
+ false
5
+ end
6
+
7
+ format :email_html do
8
+ def email_content context
9
+ content = contextual_content context
10
+ return unless content.present?
11
+ Card::Mailer.layout content
12
+ end
13
+ end
@@ -0,0 +1 @@
1
+ include_set Abstract::TestContext
@@ -0,0 +1 @@
1
+ include_set Abstract::TestContext
@@ -0,0 +1 @@
1
+ include_set Abstract::EmailField
@@ -0,0 +1,91 @@
1
+
2
+ def clean_html?
3
+ false
4
+ end
5
+
6
+ def deliver context=nil, fields={}, opts={}
7
+ mail = format.mail context, fields, opts
8
+ mail.deliver
9
+ rescue Net::SMTPError => exception
10
+ errors.add :exception, exception.message
11
+ end
12
+
13
+ format do
14
+ def mail context=nil, fields={}, opts={}
15
+ config = card.email_config context, fields, opts
16
+ fmt = self # self is <Mail::Message> within the new_mail block
17
+ Card::Mailer.new_mail config do
18
+ fmt.message_body self, config
19
+ fmt.add_attachments self, config.delete(:attach)
20
+ end
21
+ end
22
+
23
+ def message_body mail, config
24
+ config[:html_message] &&= config[:html_message].call mail
25
+ method, args = body_method_and_args config[:html_message].present?,
26
+ config[:text_message].present?
27
+ args = Array.wrap(args).map { |arg| config[arg] }
28
+ send method, mail, *args
29
+ end
30
+
31
+ def body_method_and_args html, text
32
+ if html && text
33
+ [:text_and_html_message, %i[text_message html_message attach]]
34
+ elsif html
35
+ %i[html_body html_message]
36
+ else
37
+ %i[text_body text_message]
38
+ end
39
+ end
40
+
41
+ def text_and_html_message mail, text_message, html_message, attachment_list=nil
42
+ fmt = self
43
+ if attachment_list&.any?
44
+ mail.multipart_mixed text_message, html_message
45
+ else
46
+ mail.text_part { body text_message }
47
+ mail.html_part { fmt.html_body self, html_message }
48
+ end
49
+ end
50
+
51
+ def multipart_mixed mail, text_message, html_message
52
+ mail.content_type "multipart/mixed"
53
+ mail.part content_type: "multipart/alternative" do |copy|
54
+ copy.part content_type: "text/plain" do |plain|
55
+ plain.body = text_message
56
+ end
57
+ copy.part content_type: "text/html" do |html|
58
+ html.body = html_message
59
+ end
60
+ end
61
+ end
62
+
63
+ def html_body mail, message
64
+ mail.content_type "text/html; charset=UTF-8"
65
+ mail.body message
66
+ end
67
+
68
+ def text_body mail, message
69
+ mail.content_type "text/plain; charset=UTF-8"
70
+ mail.text_part { body message }
71
+ end
72
+
73
+ def add_attachments mail, list
74
+ return unless list.present?
75
+ each_valid_attachment list do |file, index|
76
+ mail.add_file filename: attachment_name(file, index),
77
+ content: File.read(file.path)
78
+ end
79
+ end
80
+
81
+ def each_valid_attachment list
82
+ list.each_with_index do |cardname, index|
83
+ next unless (file = Card[cardname]&.try(:attachment))
84
+ yield file, index
85
+ end
86
+ end
87
+
88
+ def attachment_name file, number
89
+ "attachment-#{number + 1}.#{file.extension}"
90
+ end
91
+ end
@@ -0,0 +1,81 @@
1
+ EMAIL_FIELDS =
2
+ %i[to from cc bcc attach subject text_message html_message].freeze
3
+
4
+ EMAIL_FIELD_METHODS =
5
+ { subject: :contextual_content,
6
+ text_message: :contextual_content,
7
+ attach: :extended_item_contents }.freeze
8
+
9
+ # @param [Card] context the card in whose context all email fields will be interpreted
10
+ # @param [Hash] fields override any templated field configurations with hash values
11
+ # @param [Hash] opts options for rendering. unknown options become format options
12
+ # @option opts [Card, String, Integer] :auth user identifier. render as this user
13
+ def email_config context, fields={}, opts={}
14
+ @active_email_context = context || self
15
+ auth = opts.delete :auth
16
+ config = EMAIL_FIELDS.each_with_object({}) do |field, conf|
17
+ conf[field] = fields[field] || email_field_from_card(field, auth, opts)
18
+ end
19
+ safe_from_and_reply_to! config
20
+ config.select { |_k, v| v.present? }
21
+ end
22
+
23
+ def email_field_from_card field, auth, format_opts
24
+ return unless (field_card = fetch(field))
25
+ auth ||= field_card.updater
26
+ special_email_field_method(field, field_card, auth, format_opts) ||
27
+ standard_email_field(field, field_card, auth, format_opts)
28
+ end
29
+
30
+ def special_email_field_method field, field_card, auth, format_opts
31
+ method = "email_#{field}_field"
32
+ return unless respond_to? method
33
+ send method, field_card, auth, format_opts
34
+ end
35
+
36
+ def standard_email_field field, field_card, auth, format_opts
37
+ method = EMAIL_FIELD_METHODS[field] || :email_addresses
38
+ format_opts = format_opts.merge format: :email_text
39
+ Auth.as auth do
40
+ field_card.format(format_opts).send method, @active_email_context
41
+ end
42
+ end
43
+
44
+ # html messages return procs because image attachments can't be properly rendered
45
+ # without a mail object. (which isn't available at initial config time)
46
+ def email_html_message_field message_card, auth, format_opts
47
+ proc do |mail|
48
+ Auth.as auth do
49
+ format_opts = format_opts.merge format: :email_html, active_mail: mail
50
+ message_card.format(format_opts).email_content @active_email_context
51
+ end
52
+ end
53
+ end
54
+
55
+ # whenever a default "from" field is configured in Card::Mailer, emails are always
56
+ # actually "from" that address
57
+ def safe_from_and_reply_to! config
58
+ conf_name, conf_email = configured_from_name_and_email config[:from]
59
+ actual_email = Card::Mailer.default[:from] || conf_email
60
+ config[:from] = email_from_field_value conf_name, conf_email, actual_email
61
+ config[:reply_to] ||= actual_email
62
+ end
63
+
64
+ def email_from_field_value conf_name, conf_email, actual_email
65
+ conf_text = conf_name || conf_email
66
+ if conf_text != actual_email
67
+ %("#{conf_text}" <#{actual_email}>)
68
+ elsif actual_email.present?
69
+ actual_email
70
+ else
71
+ Card[WagnBotID].account.email
72
+ end
73
+ end
74
+
75
+ def configured_from_name_and_email raw_string
76
+ if raw_string =~ /(.*)\<(.*)>/
77
+ [Regexp.last_match(1).strip, Regexp.last_match(2)]
78
+ else
79
+ [nil, raw_string]
80
+ end
81
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: card-mod-email
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.11.0
5
+ platform: ruby
6
+ authors:
7
+ - Ethan McCutchen
8
+ - Philipp Kühl
9
+ - Gerry Gleason
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2020-12-24 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: card
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - '='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.101.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - '='
27
+ - !ruby/object:Gem::Version
28
+ version: 1.101.0
29
+ description: ''
30
+ email:
31
+ - info@decko.org
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - lib/card/format/email_html_format.rb
37
+ - lib/card/format/email_text_format.rb
38
+ - set/abstract/email_field.rb
39
+ - set/abstract/test_context.rb
40
+ - set/all/email_html.rb
41
+ - set/all/email_text.rb
42
+ - set/right/bcc.rb
43
+ - set/right/cc.rb
44
+ - set/right/from.rb
45
+ - set/right/html_message.rb
46
+ - set/right/subject.rb
47
+ - set/right/text_message.rb
48
+ - set/right/to.rb
49
+ - set/type/email_template.rb
50
+ - set/type/email_template/email_config.rb
51
+ homepage: http://decko.org
52
+ licenses:
53
+ - GPL-3.0
54
+ metadata:
55
+ card-mod: email
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '2.5'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubygems_version: 3.0.3
72
+ signing_key:
73
+ specification_version: 4
74
+ summary: Email handling
75
+ test_files: []