mail 1.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of mail might be problematic. Click here for more details.

Files changed (107) hide show
  1. data/.gitignore +4 -0
  2. data/Manifest.txt +106 -0
  3. data/README.rdoc +441 -0
  4. data/Rakefile +38 -0
  5. data/lib/mail.rb +86 -0
  6. data/lib/mail/attachment.rb +90 -0
  7. data/lib/mail/body.rb +149 -0
  8. data/lib/mail/configuration.rb +90 -0
  9. data/lib/mail/core_extensions.rb +6 -0
  10. data/lib/mail/core_extensions/blank.rb +41 -0
  11. data/lib/mail/core_extensions/nil.rb +15 -0
  12. data/lib/mail/core_extensions/string.rb +31 -0
  13. data/lib/mail/elements/address.rb +293 -0
  14. data/lib/mail/elements/address_list.rb +62 -0
  15. data/lib/mail/elements/content_disposition_element.rb +34 -0
  16. data/lib/mail/elements/content_transfer_encoding_element.rb +21 -0
  17. data/lib/mail/elements/content_type_element.rb +39 -0
  18. data/lib/mail/elements/date_time_element.rb +26 -0
  19. data/lib/mail/elements/envelope_from_element.rb +34 -0
  20. data/lib/mail/elements/message_ids_element.rb +29 -0
  21. data/lib/mail/elements/mime_version_element.rb +26 -0
  22. data/lib/mail/elements/phrase_list.rb +21 -0
  23. data/lib/mail/elements/received_element.rb +30 -0
  24. data/lib/mail/encodings/base64.rb +17 -0
  25. data/lib/mail/encodings/encodings.rb +24 -0
  26. data/lib/mail/encodings/quoted_printable.rb +26 -0
  27. data/lib/mail/envelope.rb +35 -0
  28. data/lib/mail/field.rb +202 -0
  29. data/lib/mail/field_list.rb +33 -0
  30. data/lib/mail/fields/bcc_field.rb +40 -0
  31. data/lib/mail/fields/cc_field.rb +40 -0
  32. data/lib/mail/fields/comments_field.rb +41 -0
  33. data/lib/mail/fields/common/common_address.rb +62 -0
  34. data/lib/mail/fields/common/common_date.rb +35 -0
  35. data/lib/mail/fields/common/common_field.rb +128 -0
  36. data/lib/mail/fields/common/common_message_id.rb +35 -0
  37. data/lib/mail/fields/content_description_field.rb +15 -0
  38. data/lib/mail/fields/content_disposition_field.rb +34 -0
  39. data/lib/mail/fields/content_id_field.rb +50 -0
  40. data/lib/mail/fields/content_transfer_encoding_field.rb +28 -0
  41. data/lib/mail/fields/content_type_field.rb +50 -0
  42. data/lib/mail/fields/date_field.rb +44 -0
  43. data/lib/mail/fields/from_field.rb +40 -0
  44. data/lib/mail/fields/in_reply_to_field.rb +42 -0
  45. data/lib/mail/fields/keywords_field.rb +22 -0
  46. data/lib/mail/fields/message_id_field.rb +70 -0
  47. data/lib/mail/fields/mime_version_field.rb +42 -0
  48. data/lib/mail/fields/optional_field.rb +11 -0
  49. data/lib/mail/fields/received_field.rb +49 -0
  50. data/lib/mail/fields/references_field.rb +42 -0
  51. data/lib/mail/fields/reply_to_field.rb +40 -0
  52. data/lib/mail/fields/resent_bcc_field.rb +40 -0
  53. data/lib/mail/fields/resent_cc_field.rb +40 -0
  54. data/lib/mail/fields/resent_date_field.rb +16 -0
  55. data/lib/mail/fields/resent_from_field.rb +40 -0
  56. data/lib/mail/fields/resent_message_id_field.rb +20 -0
  57. data/lib/mail/fields/resent_sender_field.rb +48 -0
  58. data/lib/mail/fields/resent_to_field.rb +40 -0
  59. data/lib/mail/fields/return_path_field.rb +34 -0
  60. data/lib/mail/fields/sender_field.rb +48 -0
  61. data/lib/mail/fields/structured_field.rb +32 -0
  62. data/lib/mail/fields/subject_field.rb +14 -0
  63. data/lib/mail/fields/to_field.rb +40 -0
  64. data/lib/mail/fields/unstructured_field.rb +27 -0
  65. data/lib/mail/header.rb +213 -0
  66. data/lib/mail/mail.rb +120 -0
  67. data/lib/mail/message.rb +648 -0
  68. data/lib/mail/network/deliverable.rb +42 -0
  69. data/lib/mail/network/retrievable.rb +63 -0
  70. data/lib/mail/parsers/address_lists.rb +61 -0
  71. data/lib/mail/parsers/address_lists.treetop +19 -0
  72. data/lib/mail/parsers/content_disposition.rb +358 -0
  73. data/lib/mail/parsers/content_disposition.treetop +45 -0
  74. data/lib/mail/parsers/content_transfer_encoding.rb +179 -0
  75. data/lib/mail/parsers/content_transfer_encoding.treetop +25 -0
  76. data/lib/mail/parsers/content_type.rb +507 -0
  77. data/lib/mail/parsers/content_type.treetop +58 -0
  78. data/lib/mail/parsers/date_time.rb +111 -0
  79. data/lib/mail/parsers/date_time.treetop +11 -0
  80. data/lib/mail/parsers/envelope_from.rb +188 -0
  81. data/lib/mail/parsers/envelope_from.treetop +32 -0
  82. data/lib/mail/parsers/message_ids.rb +42 -0
  83. data/lib/mail/parsers/message_ids.treetop +15 -0
  84. data/lib/mail/parsers/mime_version.rb +141 -0
  85. data/lib/mail/parsers/mime_version.treetop +19 -0
  86. data/lib/mail/parsers/phrase_lists.rb +42 -0
  87. data/lib/mail/parsers/phrase_lists.treetop +15 -0
  88. data/lib/mail/parsers/received.rb +68 -0
  89. data/lib/mail/parsers/received.treetop +11 -0
  90. data/lib/mail/parsers/rfc2045.rb +406 -0
  91. data/lib/mail/parsers/rfc2045.treetop +35 -0
  92. data/lib/mail/parsers/rfc2822.rb +5005 -0
  93. data/lib/mail/parsers/rfc2822.treetop +402 -0
  94. data/lib/mail/parsers/rfc2822_obsolete.rb +3607 -0
  95. data/lib/mail/parsers/rfc2822_obsolete.treetop +241 -0
  96. data/lib/mail/part.rb +120 -0
  97. data/lib/mail/patterns.rb +42 -0
  98. data/lib/mail/utilities.rb +142 -0
  99. data/lib/mail/version.rb +10 -0
  100. data/lib/mail/version_specific/multibyte.rb +62 -0
  101. data/lib/mail/version_specific/multibyte/chars.rb +701 -0
  102. data/lib/mail/version_specific/multibyte/exceptions.rb +8 -0
  103. data/lib/mail/version_specific/multibyte/unicode_database.rb +71 -0
  104. data/lib/mail/version_specific/ruby_1_8.rb +61 -0
  105. data/lib/mail/version_specific/ruby_1_8_string.rb +88 -0
  106. data/lib/mail/version_specific/ruby_1_9.rb +49 -0
  107. metadata +192 -0
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+ #
3
+ #
4
+ #
5
+ module Mail
6
+ class ContentIdField < StructuredField
7
+
8
+ FIELD_NAME = 'content-id'
9
+
10
+ def initialize(*args)
11
+ @uniq = 1
12
+ if args.last.blank?
13
+ self.name = FIELD_NAME
14
+ self.value = generate_content_id
15
+ self
16
+ else
17
+ super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
18
+ end
19
+ end
20
+
21
+ def tree
22
+ @element ||= Mail::MessageIdsElement.new(value)
23
+ @tree ||= @element.tree
24
+ end
25
+
26
+ def element
27
+ @element ||= Mail::MessageIdsElement.new(value)
28
+ end
29
+
30
+ def name
31
+ 'Content-ID'
32
+ end
33
+
34
+ def content_id
35
+ element.message_id
36
+ end
37
+
38
+ def to_s
39
+ "<#{content_id}>"
40
+ end
41
+
42
+ private
43
+
44
+ def generate_content_id
45
+ fqdn = ::Socket.gethostname
46
+ "<#{Mail.random_tag}@#{fqdn}.mail>"
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+ #
3
+ #
4
+ #
5
+ module Mail
6
+ class ContentTransferEncodingField < StructuredField
7
+
8
+ FIELD_NAME = 'content-transfer-encoding'
9
+
10
+ def initialize(*args)
11
+ super(FIELD_NAME, strip_field(FIELD_NAME, args.last.to_s.downcase))
12
+ end
13
+
14
+ def tree
15
+ @element ||= ContentTransferEncodingElement.new(value)
16
+ @tree ||= @element.tree
17
+ end
18
+
19
+ def element
20
+ @element ||= ContentTransferEncodingElement.new(value)
21
+ end
22
+
23
+ def encoding
24
+ element.encoding
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+ #
3
+ #
4
+ #
5
+ module Mail
6
+ class ContentTypeField < StructuredField
7
+
8
+ FIELD_NAME = 'content-type'
9
+
10
+ def initialize(*args)
11
+ super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
12
+ end
13
+
14
+ def tree
15
+ @element ||= Mail::ContentTypeElement.new(value)
16
+ @tree ||= @element.tree
17
+ end
18
+
19
+ def element
20
+ @element ||= Mail::ContentTypeElement.new(value)
21
+ end
22
+
23
+ def main_type
24
+ element.main_type
25
+ end
26
+
27
+ def sub_type
28
+ element.sub_type
29
+ end
30
+
31
+ def content_type
32
+ "#{main_type}/#{sub_type}"
33
+ end
34
+
35
+ def parameters
36
+ @parameters = Hash.new
37
+ element.parameters.each { |p| @parameters.merge!(p) }
38
+ @parameters
39
+ end
40
+
41
+ def ContentTypeField.with_boundary(type)
42
+ new("#{type}; boundary=#{generate_boundary}")
43
+ end
44
+
45
+ def ContentTypeField.generate_boundary
46
+ "--==_mimepart_#{Mail.random_tag}"
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+ #
3
+ # = Date Field
4
+ #
5
+ # The Date field inherits from StructuredField and handles the Date: header
6
+ # field in the email.
7
+ #
8
+ # Sending date to a mail message will instantiate a Mail::Field object that
9
+ # has a DateField as it's field type. This includes all Mail::CommonAddress
10
+ # module instance methods.
11
+ #
12
+ # There must be excatly one Date field in an RFC2822 email.
13
+ #
14
+ # == Examples:
15
+ #
16
+ # mail = Mail.new
17
+ # mail.date = 'Mon, 24 Nov 1997 14:22:01 -0800'
18
+ # mail.date #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
19
+ # mail[:date] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
20
+ # mail['date'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
21
+ # mail['Date'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
22
+ #
23
+ # mail.date.to_s #=> 'Mon, 24 Nov 1997 14:22:01 -0800'
24
+ # mail.date.date_time #=> #<DateTime: 211747170121/86400,-1/3,2299161>
25
+ #
26
+ module Mail
27
+ class DateField < StructuredField
28
+
29
+ include Mail::CommonDate
30
+
31
+ FIELD_NAME = 'date'
32
+
33
+ def initialize(*args)
34
+ if args.last.blank?
35
+ self.name = FIELD_NAME
36
+ self.value = Time.now.strftime('%a, %d %b %Y %H:%M:%S %z')
37
+ self
38
+ else
39
+ super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
40
+ end
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+ #
3
+ # = From Field
4
+ #
5
+ # The From field inherits from StructuredField and handles the From: header
6
+ # field in the email.
7
+ #
8
+ # Sending from to a mail message will instantiate a Mail::Field object that
9
+ # has a FromField as it's field type. This includes all Mail::CommonAddress
10
+ # module instance metods.
11
+ #
12
+ # Only one From field can appear in a header, though it can have multiple
13
+ # addresses and groups of addresses.
14
+ #
15
+ # == Examples:
16
+ #
17
+ # mail = Mail.new
18
+ # mail.from = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
+ # mail.from #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
20
+ # mail[:from] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
21
+ # mail['from'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
22
+ # mail['From'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
23
+ #
24
+ # mail.from.to_s #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
25
+ # mail.from.addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
26
+ # mail.from.formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
27
+ #
28
+ module Mail
29
+ class FromField < StructuredField
30
+
31
+ include Mail::CommonAddress
32
+
33
+ FIELD_NAME = 'from'
34
+
35
+ def initialize(*args)
36
+ super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+ #
3
+ # = In-Reply-To Field
4
+ #
5
+ # The In-Reply-To field inherits from StructuredField and handles the
6
+ # In-Reply-To: header field in the email.
7
+ #
8
+ # Sending in_reply_to to a mail message will instantiate a Mail::Field object that
9
+ # has a InReplyToField as it's field type. This includes all Mail::CommonMessageId
10
+ # module instance metods.
11
+ #
12
+ # Note that, the #message_ids method will return an array of message IDs without the
13
+ # enclosing angle brackets which per RFC are not syntactically part of the message id.
14
+ #
15
+ # Only one InReplyTo field can appear in a header, though it can have multiple
16
+ # Message IDs.
17
+ #
18
+ # == Examples:
19
+ #
20
+ # mail = Mail.new
21
+ # mail.in_reply_to = '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
22
+ # mail.in_reply_to #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
23
+ # mail[:in_reply_to] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
24
+ # mail['in_reply_to'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
25
+ # mail['In-Reply-To'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
26
+ #
27
+ # mail.in_reply_to.to_s #=> '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
28
+ # mail.in_reply_to.message_ids #=> ['F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom']
29
+ #
30
+ module Mail
31
+ class InReplyToField < StructuredField
32
+
33
+ include Mail::CommonMessageId
34
+
35
+ FIELD_NAME = 'in-reply-to'
36
+
37
+ def initialize(*args)
38
+ super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+ #
3
+ # keywords = "Keywords:" phrase *("," phrase) CRLF
4
+ module Mail
5
+ class KeywordsField < StructuredField
6
+
7
+ FIELD_NAME = 'keywords'
8
+
9
+ def initialize(*args)
10
+ super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
11
+ end
12
+
13
+ def phrase_list
14
+ @phrase_list ||= PhraseList.new(value)
15
+ end
16
+
17
+ def keywords
18
+ phrase_list.phrases
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,70 @@
1
+ # encoding: utf-8
2
+ #
3
+ # = Message-ID Field
4
+ #
5
+ # The Message-ID field inherits from StructuredField and handles the
6
+ # Message-ID: header field in the email.
7
+ #
8
+ # Sending message_id to a mail message will instantiate a Mail::Field object that
9
+ # has a MessageIdField as it's field type. This includes all Mail::CommonMessageId
10
+ # module instance metods.
11
+ #
12
+ # Only one MessageId field can appear in a header, and syntactically it can only have
13
+ # one Message ID. The message_ids method call has been left in however as it will only
14
+ # return the one message id, ie, an array of length 1.
15
+ #
16
+ # Note that, the #message_ids method will return an array of message IDs without the
17
+ # enclosing angle brackets which per RFC are not syntactically part of the message id.
18
+ #
19
+ # == Examples:
20
+ #
21
+ # mail = Mail.new
22
+ # mail.message_id = '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
23
+ # mail.message_id #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
24
+ # mail[:message_id] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
25
+ # mail['message_id'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
26
+ # mail['Message-ID'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
27
+ #
28
+ # mail.message_id.to_s #=> '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
29
+ # mail.message_id.message_id #=> 'F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom'
30
+ # mail.message_id.message_ids #=> ['F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom']
31
+ #
32
+ module Mail
33
+ class MessageIdField < StructuredField
34
+
35
+ include Mail::CommonMessageId
36
+
37
+ FIELD_NAME = 'message-id'
38
+
39
+ def initialize(*args)
40
+ @uniq = 1
41
+ if args.last.blank?
42
+ self.name = FIELD_NAME
43
+ self.value = generate_message_id
44
+ self
45
+ else
46
+ super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
47
+ end
48
+ end
49
+
50
+ def name
51
+ 'Message-ID'
52
+ end
53
+
54
+ def message_ids
55
+ [message_id]
56
+ end
57
+
58
+ def to_s
59
+ "<#{message_id}>"
60
+ end
61
+
62
+ private
63
+
64
+ def generate_message_id
65
+ fqdn = ::Socket.gethostname
66
+ "<#{Mail.random_tag}@#{fqdn}.mail>"
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+ #
3
+ #
4
+ #
5
+ module Mail
6
+ class MimeVersionField < StructuredField
7
+
8
+ FIELD_NAME = 'mime-version'
9
+
10
+ def initialize(*args)
11
+ if args.last.blank?
12
+ self.name = FIELD_NAME
13
+ self.value = '1.0'
14
+ self
15
+ else
16
+ super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
17
+ end
18
+ end
19
+
20
+ def tree
21
+ @element ||= MimeVersionElement.new(value)
22
+ @tree ||= @element.tree
23
+ end
24
+
25
+ def element
26
+ @element ||= MimeVersionElement.new(value)
27
+ end
28
+
29
+ def version
30
+ "#{element.major}.#{element.minor}"
31
+ end
32
+
33
+ def major
34
+ element.major.to_i
35
+ end
36
+
37
+ def minor
38
+ element.minor.to_i
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+ #
3
+ # The field names of any optional-field MUST NOT be identical to any
4
+ # field name specified elsewhere in this standard.
5
+ #
6
+ # optional-field = field-name ":" unstructured CRLF
7
+ module Mail
8
+ class OptionalField < UnstructuredField
9
+
10
+ end
11
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+ #
3
+ # trace = [return]
4
+ # 1*received
5
+ #
6
+ # return = "Return-Path:" path CRLF
7
+ #
8
+ # path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) /
9
+ # obs-path
10
+ #
11
+ # received = "Received:" name-val-list ";" date-time CRLF
12
+ #
13
+ # name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)]
14
+ #
15
+ # name-val-pair = item-name CFWS item-value
16
+ #
17
+ # item-name = ALPHA *(["-"] (ALPHA / DIGIT))
18
+ #
19
+ # item-value = 1*angle-addr / addr-spec /
20
+ # atom / domain / msg-id
21
+ #
22
+ module Mail
23
+ class ReceivedField < StructuredField
24
+
25
+ FIELD_NAME = 'received'
26
+
27
+ def initialize(*args)
28
+ super(FIELD_NAME, strip_field(FIELD_NAME, args.last))
29
+ end
30
+
31
+ def tree
32
+ @element ||= ReceivedElement.new(value)
33
+ @tree ||= @element.tree
34
+ end
35
+
36
+ def element
37
+ @element ||= ReceivedElement.new(value)
38
+ end
39
+
40
+ def date_time
41
+ ::DateTime.parse("#{element.date_time}")
42
+ end
43
+
44
+ def info
45
+ element.info
46
+ end
47
+
48
+ end
49
+ end