├── .github
└── workflows
│ └── test.yml
├── .gitignore
├── CHANGELOG.rdoc
├── CONTRIBUTING.md
├── Gemfile
├── MIT-LICENSE
├── README.md
├── Rakefile
├── lib
├── mail.rb
└── mail
│ ├── attachments_list.rb
│ ├── body.rb
│ ├── configuration.rb
│ ├── constants.rb
│ ├── elements.rb
│ ├── elements
│ ├── address.rb
│ ├── address_list.rb
│ ├── content_disposition_element.rb
│ ├── content_location_element.rb
│ ├── content_transfer_encoding_element.rb
│ ├── content_type_element.rb
│ ├── date_time_element.rb
│ ├── envelope_from_element.rb
│ ├── message_ids_element.rb
│ ├── mime_version_element.rb
│ ├── phrase_list.rb
│ └── received_element.rb
│ ├── encodings.rb
│ ├── encodings
│ ├── 7bit.rb
│ ├── 8bit.rb
│ ├── base64.rb
│ ├── binary.rb
│ ├── identity.rb
│ ├── quoted_printable.rb
│ ├── transfer_encoding.rb
│ └── unix_to_unix.rb
│ ├── envelope.rb
│ ├── field.rb
│ ├── field_list.rb
│ ├── fields.rb
│ ├── fields
│ ├── bcc_field.rb
│ ├── cc_field.rb
│ ├── comments_field.rb
│ ├── common_address_field.rb
│ ├── common_date_field.rb
│ ├── common_field.rb
│ ├── common_message_id_field.rb
│ ├── content_description_field.rb
│ ├── content_disposition_field.rb
│ ├── content_id_field.rb
│ ├── content_location_field.rb
│ ├── content_transfer_encoding_field.rb
│ ├── content_type_field.rb
│ ├── date_field.rb
│ ├── from_field.rb
│ ├── in_reply_to_field.rb
│ ├── keywords_field.rb
│ ├── message_id_field.rb
│ ├── mime_version_field.rb
│ ├── named_structured_field.rb
│ ├── named_unstructured_field.rb
│ ├── optional_field.rb
│ ├── parameter_hash.rb
│ ├── received_field.rb
│ ├── references_field.rb
│ ├── reply_to_field.rb
│ ├── resent_bcc_field.rb
│ ├── resent_cc_field.rb
│ ├── resent_date_field.rb
│ ├── resent_from_field.rb
│ ├── resent_message_id_field.rb
│ ├── resent_sender_field.rb
│ ├── resent_to_field.rb
│ ├── return_path_field.rb
│ ├── sender_field.rb
│ ├── structured_field.rb
│ ├── subject_field.rb
│ ├── to_field.rb
│ └── unstructured_field.rb
│ ├── header.rb
│ ├── indifferent_hash.rb
│ ├── mail.rb
│ ├── matchers
│ ├── attachment_matchers.rb
│ └── has_sent_mail.rb
│ ├── message.rb
│ ├── multibyte.rb
│ ├── multibyte
│ ├── chars.rb
│ ├── unicode.rb
│ └── utils.rb
│ ├── network.rb
│ ├── network
│ ├── delivery_methods
│ │ ├── exim.rb
│ │ ├── file_delivery.rb
│ │ ├── logger_delivery.rb
│ │ ├── sendmail.rb
│ │ ├── smtp.rb
│ │ ├── smtp_connection.rb
│ │ └── test_mailer.rb
│ └── retriever_methods
│ │ ├── base.rb
│ │ ├── imap.rb
│ │ ├── pop3.rb
│ │ └── test_retriever.rb
│ ├── parser_tools.rb
│ ├── parsers.rb
│ ├── parsers
│ ├── address_lists_parser.rb
│ ├── address_lists_parser.rl
│ ├── content_disposition_parser.rb
│ ├── content_disposition_parser.rl
│ ├── content_location_parser.rb
│ ├── content_location_parser.rl
│ ├── content_transfer_encoding_parser.rb
│ ├── content_transfer_encoding_parser.rl
│ ├── content_type_parser.rb
│ ├── content_type_parser.rl
│ ├── date_time_parser.rb
│ ├── date_time_parser.rl
│ ├── envelope_from_parser.rb
│ ├── envelope_from_parser.rl
│ ├── message_ids_parser.rb
│ ├── message_ids_parser.rl
│ ├── mime_version_parser.rb
│ ├── mime_version_parser.rl
│ ├── phrase_lists_parser.rb
│ ├── phrase_lists_parser.rl
│ ├── received_parser.rb
│ ├── received_parser.rl
│ ├── rfc2045_content_transfer_encoding.rl
│ ├── rfc2045_content_type.rl
│ ├── rfc2045_mime.rl
│ ├── rfc2183_content_disposition.rl
│ ├── rfc3629_utf8.rl
│ ├── rfc5234_abnf_core_rules.rl
│ ├── rfc5322.rl
│ ├── rfc5322_address.rl
│ ├── rfc5322_date_time.rl
│ └── rfc5322_lexical_tokens.rl
│ ├── part.rb
│ ├── parts_list.rb
│ ├── smtp_envelope.rb
│ ├── utilities.rb
│ ├── values
│ └── unicode_tables.dat
│ ├── version.rb
│ └── yaml.rb
├── mail.gemspec
├── rakelib
├── corpus.rake
├── generate_tables
└── ragel.rake
├── spec
├── environment.rb
├── fixtures
│ ├── attachments
│ │ ├── basic_email.eml
│ │ ├── test.gif
│ │ ├── test.jpg
│ │ ├── test.pdf
│ │ ├── test.png
│ │ ├── test.tiff
│ │ ├── test.zip
│ │ └── てすと.txt
│ └── emails
│ │ ├── .gitattributes
│ │ ├── attachment_emails
│ │ ├── attachment_content_disposition.eml
│ │ ├── attachment_content_location.eml
│ │ ├── attachment_message_rfc822.eml
│ │ ├── attachment_message_rfc822_inline_image.eml
│ │ ├── attachment_nonascii_filename.eml
│ │ ├── attachment_only_email.eml
│ │ ├── attachment_pdf.eml
│ │ ├── attachment_pdf_lf.eml
│ │ ├── attachment_pdf_non_ascii.eml
│ │ ├── attachment_pdf_non_ascii_lf.eml
│ │ ├── attachment_with_base64_encoded_name.eml
│ │ ├── attachment_with_encoded_name.eml
│ │ ├── attachment_with_quoted_filename.eml
│ │ └── attachment_with_unquoted_name.eml
│ │ ├── error_emails
│ │ ├── bad_date_header.eml
│ │ ├── bad_date_header2.eml
│ │ ├── bad_encoded_subject.eml
│ │ ├── bad_subject.eml
│ │ ├── cant_parse_from.eml
│ │ ├── content_transfer_encoding_7-bit.eml
│ │ ├── content_transfer_encoding_empty.eml
│ │ ├── content_transfer_encoding_plain.eml
│ │ ├── content_transfer_encoding_qp_with_space.eml
│ │ ├── content_transfer_encoding_spam.eml
│ │ ├── content_transfer_encoding_text-html.eml
│ │ ├── content_transfer_encoding_with_8bits.eml
│ │ ├── content_transfer_encoding_with_semi_colon.eml
│ │ ├── content_transfer_encoding_x_uuencode.eml
│ │ ├── empty_group_lists.eml
│ │ ├── empty_in_reply_to.eml
│ │ ├── encoding_madness.eml
│ │ ├── header_fields_with_empty_values.eml
│ │ ├── invalid_subject_characters.eml
│ │ ├── missing_body.eml
│ │ ├── missing_content_disposition.eml
│ │ ├── multiple_content_types.eml
│ │ ├── multiple_invalid_content_dispositions.eml
│ │ ├── multiple_references_with_one_invalid.eml
│ │ ├── must_supply_encoding.eml
│ │ ├── new_line_in_to_header.eml
│ │ ├── trademark_character_in_subject.eml
│ │ └── weird_to_header.eml
│ │ ├── mime_emails
│ │ ├── email_with_similar_boundaries.eml
│ │ ├── raw_email11.eml
│ │ ├── raw_email12.eml
│ │ ├── raw_email2.eml
│ │ ├── raw_email4.eml
│ │ ├── raw_email7.eml
│ │ ├── raw_email_encoded_stack_level_too_deep.eml
│ │ ├── raw_email_with_binary_encoded.eml
│ │ ├── raw_email_with_illegal_boundary.eml
│ │ ├── raw_email_with_mimepart_without_content_type.eml
│ │ ├── raw_email_with_multipart_mixed_quoted_boundary.eml
│ │ ├── raw_email_with_nested_attachment.eml
│ │ ├── raw_email_with_quoted_illegal_boundary.eml
│ │ ├── sig_only_email.eml
│ │ └── two_from_in_message.eml
│ │ ├── multi_charset
│ │ ├── japanese.eml
│ │ ├── japanese_attachment.eml
│ │ ├── japanese_attachment_long_name.eml
│ │ ├── japanese_iso_2022.eml
│ │ ├── japanese_shift_jis.eml
│ │ └── ks_c_5601-1987.eml
│ │ ├── multipart_report_emails
│ │ ├── multi_address_bounce1.eml
│ │ ├── multi_address_bounce2.eml
│ │ ├── multipart_report_multiple_status.eml
│ │ ├── report_422.eml
│ │ └── report_530.eml
│ │ ├── plain_emails
│ │ ├── basic_email.eml
│ │ ├── basic_email_lf.eml
│ │ ├── mix_caps_content_type.eml
│ │ ├── raw_email.eml
│ │ ├── raw_email10.eml
│ │ ├── raw_email5.eml
│ │ ├── raw_email6.eml
│ │ ├── raw_email8.eml
│ │ ├── raw_email_bad_time.eml
│ │ ├── raw_email_double_at_in_header.eml
│ │ ├── raw_email_incorrect_header.eml
│ │ ├── raw_email_multiple_from.eml
│ │ ├── raw_email_quoted_with_0d0a.eml
│ │ ├── raw_email_reply.eml
│ │ ├── raw_email_simple.eml
│ │ ├── raw_email_string_in_date_field.eml
│ │ ├── raw_email_trailing_dot.eml
│ │ ├── raw_email_with_at_display_name.eml
│ │ ├── raw_email_with_bad_date.eml
│ │ └── raw_email_with_partially_quoted_subject.eml
│ │ ├── rfc2822
│ │ ├── example01.eml
│ │ ├── example02.eml
│ │ ├── example03.eml
│ │ ├── example04.eml
│ │ ├── example05.eml
│ │ ├── example06.eml
│ │ ├── example07.eml
│ │ ├── example08.eml
│ │ ├── example09.eml
│ │ ├── example10.eml
│ │ ├── example11.eml
│ │ ├── example12.eml
│ │ ├── example13.eml
│ │ └── example14.eml
│ │ ├── rfc6532
│ │ └── utf8_headers.eml
│ │ └── sample_output_multipart
├── mail
│ ├── attachments_list_spec.rb
│ ├── body_spec.rb
│ ├── configuration_spec.rb
│ ├── core_extensions_spec.rb
│ ├── elements
│ │ ├── address_list_spec.rb
│ │ ├── address_spec.rb
│ │ ├── date_time_element_spec.rb
│ │ ├── envelope_from_element_spec.rb
│ │ ├── message_ids_element_spec.rb
│ │ ├── phrase_list_spec.rb
│ │ └── received_element_spec.rb
│ ├── encoding_spec.rb
│ ├── encodings
│ │ ├── base64_spec.rb
│ │ ├── quoted_printable_spec.rb
│ │ ├── transfer_encoding_spec.rb
│ │ └── unix_to_unix_spec.rb
│ ├── encodings_spec.rb
│ ├── example_emails_spec.rb
│ ├── field_list_spec.rb
│ ├── field_spec.rb
│ ├── fields
│ │ ├── address_container_spec.rb
│ │ ├── bcc_field_spec.rb
│ │ ├── cc_field_spec.rb
│ │ ├── comments_field_spec.rb
│ │ ├── common_address_spec.rb
│ │ ├── common_date_spec.rb
│ │ ├── common_field_spec.rb
│ │ ├── common_message_id_spec.rb
│ │ ├── content_description_field_spec.rb
│ │ ├── content_disposition_field_spec.rb
│ │ ├── content_id_field_spec.rb
│ │ ├── content_location_field_spec.rb
│ │ ├── content_transfer_encoding_field_spec.rb
│ │ ├── content_type_field_spec.rb
│ │ ├── date_field_spec.rb
│ │ ├── envelope_spec.rb
│ │ ├── from_field_spec.rb
│ │ ├── in_reply_to_field_spec.rb
│ │ ├── keywords_field_spec.rb
│ │ ├── message_id_field_spec.rb
│ │ ├── mime_version_field_spec.rb
│ │ ├── parameter_hash_spec.rb
│ │ ├── received_field_spec.rb
│ │ ├── references_field_spec.rb
│ │ ├── reply_to_field_spec.rb
│ │ ├── resent_bcc_field_spec.rb
│ │ ├── resent_cc_field_spec.rb
│ │ ├── resent_date_field_spec.rb
│ │ ├── resent_from_field_spec.rb
│ │ ├── resent_message_id_field_spec.rb
│ │ ├── resent_sender_field_spec.rb
│ │ ├── resent_to_field_spec.rb
│ │ ├── return_path_field_spec.rb
│ │ ├── sender_field_spec.rb
│ │ ├── structured_field_spec.rb
│ │ ├── to_field_spec.rb
│ │ └── unstructured_field_spec.rb
│ ├── header_spec.rb
│ ├── mail_spec.rb
│ ├── message_spec.rb
│ ├── mime_messages_spec.rb
│ ├── multibyte_spec.rb
│ ├── multipart_report_spec.rb
│ ├── network
│ │ ├── delivery_methods
│ │ │ ├── exim_spec.rb
│ │ │ ├── file_delivery_spec.rb
│ │ │ ├── logger_delivery_spec.rb
│ │ │ ├── sendmail_spec.rb
│ │ │ ├── smtp_connection_spec.rb
│ │ │ ├── smtp_spec.rb
│ │ │ └── test_mailer_spec.rb
│ │ └── retriever_methods
│ │ │ ├── imap_spec.rb
│ │ │ ├── pop3_spec.rb
│ │ │ └── test_retriever_spec.rb
│ ├── network_spec.rb
│ ├── parsers
│ │ ├── address_lists_parser_spec.rb
│ │ └── content_transfer_encoding_parser_spec.rb
│ ├── part_spec.rb
│ ├── parts_list_spec.rb
│ ├── round_tripping_spec.rb
│ ├── utilities_spec.rb
│ └── yaml_spec.rb
├── matchers
│ └── break_down_to.rb
├── matchers_spec.rb
└── spec_helper.rb
└── tools
└── console
/.gitignore:
--------------------------------------------------------------------------------
1 | /.bundle
2 | /.rbenv-vars
3 | /.ruby-version
4 | /.rvmrc
5 | /bin
6 | /corpus
7 | /coverage
8 | /Gemfile.lock
9 | /gems
10 | /lib/mail/parsers/ragel/ruby/machines/*.dot
11 | /lib/mail/parsers/ragel/ruby/machines/*.svg
12 | /mail-*.gem
13 | /rdoc
14 |
--------------------------------------------------------------------------------
/CHANGELOG.rdoc:
--------------------------------------------------------------------------------
1 | == Version 2.9.0 (unreleased)
2 |
3 | Breaking changes:
4 | * Mail::Field::FIELDS_MAP now contains class names, not Class instances (c960657)
5 |
6 | Compatibility:
7 |
8 | * Update MIME-Version to have correct case per RFC 2045 @mikel
9 |
10 | Features:
11 |
12 | * Updated README to improve around sending multipart mail @kapfenho
13 | * Add delivery_interceptors method to Mail class to fetch registered interceptors @ghousemohamed
14 |
15 | Code Improvements:
16 |
17 | * Use Rake's default rakelib/ directory @olleolleolle
18 | * refactor: Use Dir.glob only once in gemspec's "files" directive @olleolleolle
19 | * Configure RSpec's zero-monkey patching mode @olleolleolle
20 | * Added support for JRuby 9.4 @mikel
21 | * Prefer `__dir__` @olleolleolle
22 |
23 | Bug Fixes:
24 |
25 | * Regression: Preserve message-level charset when adding parts (related to Rails ActionMailer) @shields
26 | * Regression: Adding a part should not reset the mail's charset to nil @railsbob
27 |
28 | Performance:
29 |
30 | * reduce object allocations by replacing =~ and Regexp#match by Regexp#match? @ahorek
31 | * reduce object allocations by replacing String#unpack[0] by String#unpack1 @ahorek
32 |
33 |
34 | Please check [2-8-stable](https://github.com/mikel/mail/blob/2-8-stable/CHANGELOG.rdoc) for previous changes.
35 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gemspec
4 |
5 | if ENV['MBCHARS'] # see spec/environment.rb
6 | if RUBY_VERSION < '2.7.0'
7 | gem 'activesupport', '< 6'
8 | else
9 | gem 'activesupport', :git => 'https://github.com/rails/rails', :branch => 'main'
10 | end
11 | end
12 |
13 | gem 'jruby-openssl', :platforms => :jruby
14 |
15 | gem 'mini_mime'
16 |
17 | gem 'byebug', :platforms => :mri
18 |
--------------------------------------------------------------------------------
/MIT-LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009-2016 Mikel Lindsaar
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | 'Software'), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | if !ENV["APPRAISAL_INITIALIZED"] && !ENV["CI"]
2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('Gemfile', __dir__)
3 | end
4 | require 'rubygems'
5 | require 'bundler/setup'
6 |
7 | require 'rake/testtask'
8 | require 'rspec/core/rake_task'
9 |
10 | desc "Build a gem file"
11 | task :build do
12 | system "gem build mail.gemspec"
13 | end
14 |
15 | task :default => :spec
16 |
17 | RSpec::Core::RakeTask.new(:spec) do |t|
18 | t.ruby_opts = '-w'
19 | t.rspec_opts = %w(--backtrace --color)
20 | end
21 |
--------------------------------------------------------------------------------
/lib/mail.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | module Mail # :doc:
4 |
5 | require 'date'
6 | require 'shellwords'
7 |
8 | require 'uri'
9 | require 'net/smtp'
10 | require 'mini_mime'
11 |
12 | require 'mail/version'
13 |
14 | require 'mail/indifferent_hash'
15 |
16 | require 'mail/multibyte'
17 |
18 | require 'mail/constants'
19 | require 'mail/utilities'
20 | require 'mail/configuration'
21 |
22 | @@autoloads = {}
23 | def self.register_autoload(name, path)
24 | @@autoloads[name] = path
25 | autoload(name, path)
26 | end
27 |
28 | # This runs through the autoload list and explictly requires them for you.
29 | # Useful when running mail in a threaded process.
30 | #
31 | # Usage:
32 | #
33 | # require 'mail'
34 | # Mail.eager_autoload!
35 | def self.eager_autoload!
36 | @@autoloads.each { |_,path| require(path) }
37 | end
38 |
39 | # Autoload mail send and receive classes.
40 | require 'mail/network'
41 |
42 | require 'mail/message'
43 | require 'mail/part'
44 | require 'mail/header'
45 | require 'mail/parts_list'
46 | require 'mail/attachments_list'
47 | require 'mail/body'
48 | require 'mail/field'
49 | require 'mail/field_list'
50 |
51 | register_autoload :Envelope, 'mail/envelope'
52 |
53 | # Autoload header field elements and transfer encodings.
54 | require 'mail/elements'
55 | require 'mail/encodings'
56 | require 'mail/encodings/base64'
57 | require 'mail/encodings/quoted_printable'
58 | require 'mail/encodings/unix_to_unix'
59 |
60 | require 'mail/matchers/has_sent_mail'
61 | require 'mail/matchers/attachment_matchers'
62 |
63 | # Finally... require all the Mail.methods
64 | require 'mail/mail'
65 | end
66 |
--------------------------------------------------------------------------------
/lib/mail/configuration.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | #
4 | # Thanks to Nicolas Fouché for this wrapper
5 | #
6 | require 'singleton'
7 |
8 | module Mail
9 |
10 | # The Configuration class is a Singleton used to hold the default
11 | # configuration for all Mail objects.
12 | #
13 | # Each new mail object gets a copy of these values at initialization
14 | # which can be overwritten on a per mail object basis.
15 | class Configuration
16 | include Singleton
17 |
18 | def initialize
19 | @delivery_method = nil
20 | @retriever_method = nil
21 | super
22 | end
23 |
24 | def delivery_method(method = nil, settings = {})
25 | return @delivery_method if @delivery_method && method.nil?
26 | @delivery_method = lookup_delivery_method(method).new(settings)
27 | end
28 |
29 | def lookup_delivery_method(method)
30 | case method.is_a?(String) ? method.to_sym : method
31 | when nil
32 | Mail::SMTP
33 | when :smtp
34 | Mail::SMTP
35 | when :sendmail
36 | Mail::Sendmail
37 | when :exim
38 | Mail::Exim
39 | when :file
40 | Mail::FileDelivery
41 | when :smtp_connection
42 | Mail::SMTPConnection
43 | when :test
44 | Mail::TestMailer
45 | when :logger
46 | Mail::LoggerDelivery
47 | else
48 | method
49 | end
50 | end
51 |
52 | def retriever_method(method = nil, settings = {})
53 | return @retriever_method if @retriever_method && method.nil?
54 | @retriever_method = lookup_retriever_method(method).new(settings)
55 | end
56 |
57 | def lookup_retriever_method(method)
58 | case method
59 | when nil
60 | Mail::POP3
61 | when :pop3
62 | Mail::POP3
63 | when :imap
64 | Mail::IMAP
65 | when :test
66 | Mail::TestRetriever
67 | else
68 | method
69 | end
70 | end
71 |
72 | def param_encode_language(value = nil)
73 | value ? @encode_language = value : @encode_language ||= 'en'
74 | end
75 |
76 | end
77 |
78 | end
79 |
--------------------------------------------------------------------------------
/lib/mail/elements.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module Mail
3 | register_autoload :Address, 'mail/elements/address'
4 | register_autoload :AddressList, 'mail/elements/address_list'
5 | register_autoload :ContentDispositionElement, 'mail/elements/content_disposition_element'
6 | register_autoload :ContentLocationElement, 'mail/elements/content_location_element'
7 | register_autoload :ContentTransferEncodingElement, 'mail/elements/content_transfer_encoding_element'
8 | register_autoload :ContentTypeElement, 'mail/elements/content_type_element'
9 | register_autoload :DateTimeElement, 'mail/elements/date_time_element'
10 | register_autoload :EnvelopeFromElement, 'mail/elements/envelope_from_element'
11 | register_autoload :MessageIdsElement, 'mail/elements/message_ids_element'
12 | register_autoload :MimeVersionElement, 'mail/elements/mime_version_element'
13 | register_autoload :PhraseList, 'mail/elements/phrase_list'
14 | register_autoload :ReceivedElement, 'mail/elements/received_element'
15 | end
16 |
--------------------------------------------------------------------------------
/lib/mail/elements/address_list.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/parsers/address_lists_parser'
4 |
5 | module Mail
6 | class AddressList #:nodoc:
7 | attr_reader :addresses, :group_names
8 |
9 | # Mail::AddressList is the class that parses To, From and other address fields from
10 | # emails passed into Mail.
11 | #
12 | # AddressList provides a way to query the groups and mailbox lists of the passed in
13 | # string.
14 | #
15 | # It can supply all addresses in an array, or return each address as an address object.
16 | #
17 | # Mail::AddressList requires a correctly formatted group or mailbox list per RFC2822 or
18 | # RFC822. It also handles all obsolete versions in those RFCs.
19 | #
20 | # list = 'ada@test.lindsaar.net, My Group: mikel@test.lindsaar.net, Bob <bob@test.lindsaar.net>;'
21 | # a = AddressList.new(list)
22 | # a.addresses #=> [#<Mail::Address:14943130 Address: |ada@test.lindsaar.net...
23 | # a.group_names #=> ["My Group"]
24 | def initialize(string)
25 | address_list = Parsers::AddressListsParser.parse(string)
26 | @addresses = address_list.addresses.map { |a| Address.new(a) }
27 | @group_names = address_list.group_names
28 | end
29 |
30 | def addresses_grouped_by_group
31 | addresses.select(&:group).group_by(&:group)
32 | end
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/lib/mail/elements/content_disposition_element.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/parsers/content_disposition_parser'
4 |
5 | module Mail
6 | class ContentDispositionElement #:nodoc:
7 | attr_reader :disposition_type, :parameters
8 |
9 | def initialize(string)
10 | content_disposition = Mail::Parsers::ContentDispositionParser.parse(cleaned(string))
11 | @disposition_type = content_disposition.disposition_type
12 | @parameters = content_disposition.parameters
13 | end
14 |
15 | private
16 | def cleaned(string)
17 | string =~ /(.+);\s*$/ ? $1 : string
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/lib/mail/elements/content_location_element.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/parsers/content_location_parser'
4 |
5 | module Mail
6 | class ContentLocationElement #:nodoc:
7 | attr_reader :location
8 |
9 | def initialize(string)
10 | @location = Mail::Parsers::ContentLocationParser.parse(string).location
11 | end
12 |
13 | def to_s(*args)
14 | location.to_s
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/lib/mail/elements/content_transfer_encoding_element.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/parsers/content_transfer_encoding_parser'
4 |
5 | module Mail
6 | class ContentTransferEncodingElement #:nodoc:
7 | attr_reader :encoding
8 |
9 | def initialize(string)
10 | @encoding = Mail::Parsers::ContentTransferEncodingParser.parse(string).encoding
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/lib/mail/elements/content_type_element.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/parsers/content_type_parser'
4 |
5 | module Mail
6 | class ContentTypeElement #:nodoc:
7 | attr_reader :main_type, :sub_type, :parameters
8 |
9 | def initialize(string)
10 | content_type = Mail::Parsers::ContentTypeParser.parse(cleaned(string))
11 | @main_type = content_type.main_type
12 | @sub_type = content_type.sub_type
13 | @parameters = content_type.parameters
14 | end
15 |
16 | private
17 | def cleaned(string)
18 | if string =~ /;\s*$/
19 |
20 | else
21 | string
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/lib/mail/elements/date_time_element.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/parsers/date_time_parser'
4 |
5 | module Mail
6 | class DateTimeElement #:nodoc:
7 | attr_reader :date_string, :time_string
8 |
9 | def initialize(string)
10 | date_time = Mail::Parsers::DateTimeParser.parse(string)
11 | @date_string = date_time.date_string
12 | @time_string = date_time.time_string
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/lib/mail/elements/envelope_from_element.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/parsers/envelope_from_parser'
4 | require 'date'
5 |
6 | module Mail
7 | class EnvelopeFromElement #:nodoc:
8 | attr_reader :date_time, :address
9 |
10 | def initialize(string)
11 | envelope_from = Mail::Parsers::EnvelopeFromParser.parse(string)
12 | @address = envelope_from.address
13 | @date_time = ::DateTime.parse(envelope_from.ctime_date) if envelope_from.ctime_date
14 | end
15 |
16 | # RFC 4155:
17 | # a timestamp indicating the UTC date and time when the message
18 | # was originally received, conformant with the syntax of the
19 | # traditional UNIX 'ctime' output sans timezone (note that the
20 | # use of UTC precludes the need for a timezone indicator);
21 | def formatted_date_time
22 | if date_time
23 | if date_time.respond_to?(:ctime)
24 | date_time.ctime
25 | else
26 | date_time.strftime '%a %b %e %T %Y'
27 | end
28 | end
29 | end
30 |
31 | def to_s
32 | if date_time
33 | "#{address} #{formatted_date_time}"
34 | else
35 | address
36 | end
37 | end
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/lib/mail/elements/message_ids_element.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/parsers/message_ids_parser'
4 | require 'mail/utilities'
5 |
6 | module Mail
7 | class MessageIdsElement #:nodoc:
8 | def self.parse(string)
9 | new(string).tap(&:message_ids)
10 | end
11 |
12 | attr_reader :message_ids
13 |
14 | def initialize(string)
15 | @message_ids = parse(string)
16 | end
17 |
18 | def message_id
19 | message_ids.first
20 | end
21 |
22 | private
23 | def parse(string)
24 | if Utilities.blank? string
25 | []
26 | else
27 | Mail::Parsers::MessageIdsParser.parse(string).message_ids
28 | end
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/lib/mail/elements/mime_version_element.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/parsers/mime_version_parser'
4 |
5 | module Mail
6 | class MimeVersionElement #:nodoc:
7 | attr_reader :major, :minor
8 |
9 | def initialize(string)
10 | mime_version = Mail::Parsers::MimeVersionParser.parse(string)
11 | @major = mime_version.major
12 | @minor = mime_version.minor
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/lib/mail/elements/phrase_list.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/parsers/phrase_lists_parser'
4 | require 'mail/utilities'
5 |
6 | module Mail
7 | class PhraseList #:nodoc:
8 | attr_reader :phrases
9 |
10 | def initialize(string)
11 | @phrases =
12 | if Utilities.blank? string
13 | []
14 | else
15 | Mail::Parsers::PhraseListsParser.parse(string).phrases.map { |p| Mail::Utilities.unquote(p) }
16 | end
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/lib/mail/elements/received_element.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/parsers/received_parser'
4 | require 'mail/utilities'
5 | require 'date'
6 |
7 | module Mail
8 | class ReceivedElement #:nodoc:
9 | attr_reader :info, :date_time
10 |
11 | def initialize(string)
12 | if Utilities.blank? string
13 | @date_time = nil
14 | @info = nil
15 | else
16 | received = Mail::Parsers::ReceivedParser.parse(string)
17 | @date_time = datetime_for(received)
18 | @info = received.info
19 | end
20 | end
21 |
22 | def to_s(*args)
23 | "#{info}; #{date_time.to_s(*args)}"
24 | end
25 |
26 | private
27 | def datetime_for(received)
28 | ::DateTime.parse("#{received.date} #{received.time}")
29 | rescue ArgumentError => e
30 | raise e unless e.message == 'invalid date'
31 | warn "WARNING: Invalid date field for received element (#{received.date} #{received.time}): #{e.class}: #{e.message}"
32 | nil
33 | end
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/lib/mail/encodings/7bit.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/encodings/8bit'
4 |
5 | module Mail
6 | module Encodings
7 | # 7bit and 8bit are equivalent. 7bit encoding is for text only.
8 | class SevenBit < EightBit
9 | NAME = '7bit'
10 | PRIORITY = 1
11 | Encodings.register(NAME, self)
12 |
13 | def self.decode(str)
14 | ::Mail::Utilities.binary_unsafe_to_lf str
15 | end
16 |
17 | def self.encode(str)
18 | ::Mail::Utilities.binary_unsafe_to_crlf str
19 | end
20 |
21 | # Per RFC 2045 2.7. 7bit Data, No octets with decimal values greater than 127 are allowed.
22 | def self.compatible_input?(str)
23 | str.ascii_only? && super
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/lib/mail/encodings/8bit.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/encodings/binary'
4 |
5 | module Mail
6 | module Encodings
7 | class EightBit < Binary
8 | NAME = '8bit'
9 | PRIORITY = 4
10 | Encodings.register(NAME, self)
11 |
12 | # Per RFC 2821 4.5.3.1, SMTP lines may not be longer than 1000 octets including the <CRLF>.
13 | def self.compatible_input?(str)
14 | !str.lines.find { |line| line.bytesize > 998 }
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/lib/mail/encodings/base64.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/encodings/7bit'
4 |
5 | module Mail
6 | module Encodings
7 | # Base64 encoding handles binary content at the cost of 4 output bytes
8 | # per input byte.
9 | class Base64 < SevenBit
10 | NAME = 'base64'
11 | PRIORITY = 3
12 | Encodings.register(NAME, self)
13 |
14 | def self.can_encode?(enc)
15 | true
16 | end
17 |
18 | def self.decode(str)
19 | Utilities.decode_base64(str)
20 | end
21 |
22 | def self.encode(str)
23 | ::Mail::Utilities.binary_unsafe_to_crlf(Utilities.encode_base64(str))
24 | end
25 |
26 | # 3 bytes in -> 4 bytes out
27 | def self.cost(str)
28 | 4.0 / 3
29 | end
30 |
31 | # Ruby Base64 inserts newlines automatically, so it doesn't exceed
32 | # SMTP line length limits.
33 | def self.compatible_input?(str)
34 | true
35 | end
36 | end
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/lib/mail/encodings/binary.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/encodings/identity'
4 |
5 | module Mail
6 | module Encodings
7 | class Binary < Identity
8 | NAME = 'binary'
9 | PRIORITY = 5
10 | Encodings.register(NAME, self)
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/lib/mail/encodings/identity.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/encodings/transfer_encoding'
4 |
5 | module Mail
6 | module Encodings
7 | # Identity encodings do no encoding/decoding and have a fixed cost:
8 | # 1 byte in -> 1 byte out.
9 | class Identity < TransferEncoding #:nodoc:
10 | def self.decode(str)
11 | str
12 | end
13 |
14 | def self.encode(str)
15 | str
16 | end
17 |
18 | # 1 output byte per input byte.
19 | def self.cost(str)
20 | 1.0
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/lib/mail/encodings/quoted_printable.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/encodings/7bit'
4 |
5 | module Mail
6 | module Encodings
7 | class QuotedPrintable < SevenBit
8 | NAME='quoted-printable'
9 |
10 | PRIORITY = 2
11 |
12 | def self.can_encode?(enc)
13 | EightBit.can_encode? enc
14 | end
15 |
16 | # Decode the string from Quoted-Printable. Cope with hard line breaks
17 | # that were incorrectly encoded as hex instead of literal CRLF.
18 | def self.decode(str)
19 | ::Mail::Utilities.to_lf ::Mail::Utilities.to_crlf(str).gsub(/(?:=0D=0A|=0D|=0A)\r\n/, "\r\n").unpack1("M*")
20 | end
21 |
22 | def self.encode(str)
23 | ::Mail::Utilities.to_crlf [::Mail::Utilities.to_lf(str)].pack("M")
24 | end
25 |
26 | def self.cost(str)
27 | # These bytes probably do not need encoding
28 | c = str.count("\x9\xA\xD\x20-\x3C\x3E-\x7E")
29 | # Everything else turns into =XX where XX is a
30 | # two digit hex number (taking 3 bytes)
31 | total = (str.bytesize - c)*3 + c
32 | total.to_f/str.bytesize
33 | end
34 |
35 | # QP inserts newlines automatically and cannot violate the SMTP spec.
36 | def self.compatible_input?(str)
37 | true
38 | end
39 |
40 | private
41 |
42 | Encodings.register(NAME, self)
43 | end
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/lib/mail/encodings/unix_to_unix.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module Mail
3 | module Encodings
4 | class UnixToUnix < TransferEncoding
5 | NAME = "x-uuencode"
6 |
7 | def self.decode(str)
8 | str.sub(/\Abegin \d+ [^\n]*\n/, '').unpack1('u')
9 | end
10 |
11 | def self.encode(str)
12 | [str].pack("u")
13 | end
14 |
15 | Encodings.register(NAME, self)
16 | Encodings.register("uuencode", self)
17 | Encodings.register("x-uue", self)
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/lib/mail/envelope.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | #
4 | # = Mail Envelope
5 | #
6 | # The Envelope class provides a field for the first line in an
7 | # mbox file, that looks like "From mikel@test.lindsaar.net DATETIME"
8 | #
9 | # This envelope class reads that line, and turns it into an
10 | # Envelope.from and Envelope.date for your use.
11 |
12 | module Mail
13 | class Envelope < NamedStructuredField
14 | NAME = 'Envelope-From'
15 |
16 | def element
17 | @element ||= Mail::EnvelopeFromElement.new(value)
18 | end
19 |
20 | def from
21 | element.address
22 | end
23 |
24 | def date
25 | element.date_time
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/lib/mail/fields/bcc_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # = Blind Carbon Copy Field
6 | #
7 | # The Bcc field inherits from StructuredField and handles the Bcc: header
8 | # field in the email.
9 | #
10 | # Sending bcc to a mail message will instantiate a Mail::Field object that
11 | # has a BccField as its field type. This includes all Mail::CommonAddress
12 | # module instance metods.
13 | #
14 | # Only one Bcc field can appear in a header, though it can have multiple
15 | # addresses and groups of addresses.
16 | #
17 | # == Examples:
18 | #
19 | # mail = Mail.new
20 | # mail.bcc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
21 | # mail.bcc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
22 | # mail[:bcc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
23 | # mail['bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
24 | # mail['Bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::BccField:0x180e1c4
25 | #
26 | # mail[:bcc].encoded #=> '' # Bcc field does not get output into an email
27 | # mail[:bcc].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
28 | # mail[:bcc].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
29 | # mail[:bcc].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
30 | class BccField < CommonAddressField #:nodoc:
31 | NAME = 'Bcc'
32 |
33 | attr_accessor :include_in_headers
34 |
35 | def initialize(value = nil, charset = nil)
36 | super
37 | self.include_in_headers = false
38 | end
39 |
40 | # Bcc field should not be :encoded by default
41 | def encoded
42 | if include_in_headers
43 | super
44 | else
45 | ''
46 | end
47 | end
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/lib/mail/fields/cc_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # = Carbon Copy Field
6 | #
7 | # The Cc field inherits from StructuredField and handles the Cc: header
8 | # field in the email.
9 | #
10 | # Sending cc to a mail message will instantiate a Mail::Field object that
11 | # has a CcField as its field type. This includes all Mail::CommonAddress
12 | # module instance metods.
13 | #
14 | # Only one Cc field can appear in a header, though it can have multiple
15 | # addresses and groups of addresses.
16 | #
17 | # == Examples:
18 | #
19 | # mail = Mail.new
20 | # mail.cc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
21 | # mail.cc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
22 | # mail[:cc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
23 | # mail['cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
24 | # mail['Cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CcField:0x180e1c4
25 | #
26 | # mail[:cc].encoded #=> 'Cc: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
27 | # mail[:cc].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
28 | # mail[:cc].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
29 | # mail[:cc].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
30 | class CcField < CommonAddressField #:nodoc:
31 | NAME = 'Cc'
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/lib/mail/fields/comments_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # = Comments Field
6 | #
7 | # The Comments field inherits from UnstructuredField and handles the Comments:
8 | # header field in the email.
9 | #
10 | # Sending comments to a mail message will instantiate a Mail::Field object that
11 | # has a CommentsField as its field type.
12 | #
13 | # An email header can have as many comments fields as it wants. There is no upper
14 | # limit, the comments field is also optional (that is, no comment is needed)
15 | #
16 | # == Examples:
17 | #
18 | # mail = Mail.new
19 | # mail.comments = 'This is a comment'
20 | # mail.comments #=> 'This is a comment'
21 | # mail[:comments] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CommentsField:0x180e1c4
22 | # mail['comments'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CommentsField:0x180e1c4
23 | # mail['comments'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CommentsField:0x180e1c4
24 | #
25 | # mail.comments = "This is another comment"
26 | # mail[:comments].map { |c| c.to_s }
27 | # #=> ['This is a comment', "This is another comment"]
28 | class CommentsField < NamedUnstructuredField #:nodoc:
29 | NAME = 'Comments'
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/lib/mail/fields/common_date_field.rb:
--------------------------------------------------------------------------------
1 | require 'mail/utilities'
2 |
3 | module Mail
4 | class CommonDateField < NamedStructuredField #:nodoc:
5 | def self.singular?
6 | true
7 | end
8 |
9 | def self.normalize_datetime(string)
10 | if Utilities.blank?(string)
11 | datetime = ::DateTime.now
12 | else
13 | stripped = string.to_s.gsub(/\(.*?\)/, '').squeeze(' ')
14 | begin
15 | datetime = ::DateTime.parse(stripped)
16 | rescue ArgumentError => e
17 | raise unless 'invalid date' == e.message
18 | end
19 | end
20 |
21 | if datetime
22 | datetime.strftime('%a, %d %b %Y %H:%M:%S %z')
23 | else
24 | string
25 | end
26 | end
27 |
28 | def initialize(value = nil, charset = nil)
29 | super self.class.normalize_datetime(value), charset
30 | end
31 |
32 | # Returns a date time object of the parsed date
33 | def date_time
34 | ::DateTime.parse("#{element.date_string} #{element.time_string}")
35 | rescue ArgumentError => e
36 | raise e unless e.message == 'invalid date'
37 | end
38 |
39 | def default
40 | date_time
41 | end
42 |
43 | def element
44 | @element ||= Mail::DateTimeElement.new(value)
45 | end
46 |
47 | private
48 | def do_encode
49 | "#{name}: #{value}\r\n"
50 | end
51 |
52 | def do_decode
53 | value.to_s
54 | end
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/lib/mail/fields/common_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/constants'
4 |
5 | module Mail
6 | class CommonField #:nodoc:
7 | def self.singular?
8 | false
9 | end
10 |
11 | def self.parse(*args)
12 | new(*args).tap(&:parse)
13 | end
14 |
15 | attr_accessor :name
16 | attr_reader :value
17 | attr_accessor :charset
18 | attr_reader :errors
19 |
20 | def initialize(name = nil, value = nil, charset = nil)
21 | @errors = []
22 |
23 | self.name = name
24 | self.value = value
25 | self.charset = charset || 'utf-8'
26 | end
27 |
28 | def singular?
29 | self.class.singular?
30 | end
31 |
32 | def value=(value)
33 | @element = nil
34 | @value = value.is_a?(Array) ? value : value.to_s
35 | parse
36 | end
37 |
38 | def parse
39 | tap(&:element)
40 | end
41 |
42 | def element
43 | nil
44 | end
45 |
46 | def to_s
47 | decoded.to_s
48 | end
49 |
50 | def default
51 | decoded
52 | end
53 |
54 | def decoded
55 | do_decode
56 | end
57 |
58 | def encoded
59 | do_encode
60 | end
61 |
62 | def responsible_for?(field_name)
63 | name.to_s.casecmp(field_name.to_s) == 0
64 | end
65 |
66 | private
67 |
68 | FILENAME_RE = /\b(filename|name)=([^;"\r\n]+\s[^;"\r\n]+)/
69 | def ensure_filename_quoted(value)
70 | if value.is_a?(String)
71 | value.sub FILENAME_RE, '\1="\2"'
72 | else
73 | value
74 | end
75 | end
76 | end
77 | end
78 |
--------------------------------------------------------------------------------
/lib/mail/fields/common_message_id_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/utilities'
4 |
5 | module Mail
6 | class CommonMessageIdField < NamedStructuredField #:nodoc:
7 | def element
8 | @element ||= Mail::MessageIdsElement.new(value)
9 | end
10 |
11 | def message_id
12 | element.message_id
13 | end
14 |
15 | def message_ids
16 | element.message_ids
17 | end
18 |
19 | def default
20 | ids = message_ids
21 | ids.one? ? ids.first : ids
22 | end
23 |
24 | def to_s
25 | decoded.to_s
26 | end
27 |
28 | private
29 | def do_encode
30 | %Q{#{name}: #{formatted_message_ids("\r\n ")}\r\n}
31 | end
32 |
33 | def do_decode
34 | formatted_message_ids
35 | end
36 |
37 | def formatted_message_ids(join = ' ')
38 | message_ids.map { |m| "<#{m}>" }.join(join) if message_ids.any?
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/lib/mail/fields/content_description_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | class ContentDescriptionField < NamedUnstructuredField #:nodoc:
6 | NAME = 'Content-Description'
7 |
8 | def self.singular?
9 | true
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/lib/mail/fields/content_disposition_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | class ContentDispositionField < NamedStructuredField #:nodoc:
6 | NAME = 'Content-Disposition'
7 |
8 | def self.singular?
9 | true
10 | end
11 |
12 | def initialize(value = nil, charset = nil)
13 | super ensure_filename_quoted(value), charset
14 | end
15 |
16 | def element
17 | @element ||= Mail::ContentDispositionElement.new(value)
18 | end
19 |
20 | def disposition_type
21 | element.disposition_type
22 | end
23 |
24 | def parameters
25 | @parameters = ParameterHash.new
26 | element.parameters.each { |p| @parameters.merge!(p) } unless element.parameters.nil?
27 | @parameters
28 | end
29 |
30 | def filename
31 | @filename ||= parameters['filename'] || parameters['name']
32 | end
33 |
34 | def encoded
35 | p = ";\r\n\s#{parameters.encoded}" if parameters.length > 0
36 | "#{name}: #{disposition_type}#{p}\r\n"
37 | end
38 |
39 | def decoded
40 | p = "; #{parameters.decoded}" if parameters.length > 0
41 | "#{disposition_type}#{p}"
42 | end
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/lib/mail/fields/content_id_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/utilities'
4 |
5 | module Mail
6 | class ContentIdField < NamedStructuredField #:nodoc:
7 | NAME = 'Content-ID'
8 |
9 | def self.singular?
10 | true
11 | end
12 |
13 | def initialize(value = nil, charset = nil)
14 | value = Mail::Utilities.generate_message_id if Utilities.blank?(value)
15 | super value, charset
16 | end
17 |
18 | def element
19 | @element ||= Mail::MessageIdsElement.new(value)
20 | end
21 |
22 | def content_id
23 | element.message_id
24 | end
25 |
26 | private
27 | def do_decode
28 | "<#{content_id}>"
29 | end
30 |
31 | def do_encode
32 | "#{name}: #{do_decode}\r\n"
33 | end
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/lib/mail/fields/content_location_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | class ContentLocationField < NamedStructuredField #:nodoc:
6 | NAME = 'Content-Location'
7 |
8 | def self.singular?
9 | true
10 | end
11 |
12 | def element
13 | @element ||= Mail::ContentLocationElement.new(value)
14 | end
15 |
16 | def location
17 | element.location
18 | end
19 |
20 | def encoded
21 | "#{name}: #{location}\r\n"
22 | end
23 |
24 | def decoded
25 | location
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/lib/mail/fields/content_transfer_encoding_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | class ContentTransferEncodingField < NamedStructuredField #:nodoc:
6 | NAME = 'Content-Transfer-Encoding'
7 |
8 | def self.singular?
9 | true
10 | end
11 |
12 | def self.normalize_content_transfer_encoding(value)
13 | case value
14 | when /7-?bits?/i
15 | '7bit'
16 | when /8-?bits?/i
17 | '8bit'
18 | else
19 | value
20 | end
21 | end
22 |
23 | def initialize(value = nil, charset = nil)
24 | super self.class.normalize_content_transfer_encoding(value), charset
25 | end
26 |
27 | def element
28 | @element ||= Mail::ContentTransferEncodingElement.new(value)
29 | end
30 |
31 | def encoding
32 | element.encoding
33 | end
34 |
35 | private
36 | def do_encode
37 | "#{name}: #{encoding}\r\n"
38 | end
39 |
40 | def do_decode
41 | encoding
42 | end
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/lib/mail/fields/date_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # = Date Field
6 | #
7 | # The Date field inherits from StructuredField and handles the Date: header
8 | # field in the email.
9 | #
10 | # Sending date to a mail message will instantiate a Mail::Field object that
11 | # has a DateField as its field type. This includes all Mail::CommonAddress
12 | # module instance methods.
13 | #
14 | # There must be excatly one Date field in an RFC2822 email.
15 | #
16 | # == Examples:
17 | #
18 | # mail = Mail.new
19 | # mail.date = 'Mon, 24 Nov 1997 14:22:01 -0800'
20 | # mail.date #=> #<DateTime: 211747170121/86400,-1/3,2299161>
21 | # mail.date.to_s #=> 'Mon, 24 Nov 1997 14:22:01 -0800'
22 | # mail[:date] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
23 | # mail['date'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
24 | # mail['Date'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
25 | class DateField < CommonDateField #:nodoc:
26 | NAME = 'Date'
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/lib/mail/fields/from_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # = From Field
6 | #
7 | # The From field inherits from StructuredField and handles the From: header
8 | # field in the email.
9 | #
10 | # Sending from to a mail message will instantiate a Mail::Field object that
11 | # has a FromField as its field type. This includes all Mail::CommonAddress
12 | # module instance metods.
13 | #
14 | # Only one From field can appear in a header, though it can have multiple
15 | # addresses and groups of addresses.
16 | #
17 | # == Examples:
18 | #
19 | # mail = Mail.new
20 | # mail.from = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
21 | # mail.from #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
22 | # mail[:from] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
23 | # mail['from'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
24 | # mail['From'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
25 | #
26 | # mail[:from].encoded #=> 'from: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
27 | # mail[:from].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
28 | # mail[:from].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
29 | # mail[:from].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
30 | class FromField < CommonAddressField #:nodoc:
31 | NAME = 'From'
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/lib/mail/fields/in_reply_to_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # = In-Reply-To Field
6 | #
7 | # The In-Reply-To field inherits from StructuredField and handles the
8 | # In-Reply-To: header field in the email.
9 | #
10 | # Sending in_reply_to to a mail message will instantiate a Mail::Field object that
11 | # has a InReplyToField as its field type. This includes all Mail::CommonMessageId
12 | # module instance metods.
13 | #
14 | # Note that, the #message_ids method will return an array of message IDs without the
15 | # enclosing angle brackets which per RFC are not syntactically part of the message id.
16 | #
17 | # Only one InReplyTo field can appear in a header, though it can have multiple
18 | # Message IDs.
19 | #
20 | # == Examples:
21 | #
22 | # mail = Mail.new
23 | # mail.in_reply_to = '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
24 | # mail.in_reply_to #=> '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
25 | # mail[:in_reply_to] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
26 | # mail['in_reply_to'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
27 | # mail['In-Reply-To'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
28 | #
29 | # mail[:in_reply_to].message_ids #=> ['F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom']
30 | class InReplyToField < CommonMessageIdField #:nodoc:
31 | NAME = 'In-Reply-To'
32 |
33 | def self.singular?
34 | true
35 | end
36 |
37 | def initialize(value = nil, charset = nil)
38 | if value.is_a?(Array)
39 | super value.join("\r\n\s"), charset
40 | else
41 | super
42 | end
43 | end
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/lib/mail/fields/keywords_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # keywords = "Keywords:" phrase *("," phrase) CRLF
6 | class KeywordsField < NamedStructuredField #:nodoc:
7 | NAME = 'Keywords'
8 |
9 | def element
10 | @element ||= PhraseList.new(value)
11 | end
12 |
13 | def keywords
14 | element.phrases
15 | end
16 |
17 | def default
18 | keywords
19 | end
20 |
21 | private
22 | def do_decode
23 | keywords.join(', ')
24 | end
25 |
26 | def do_encode
27 | "#{name}: #{keywords.join(",\r\n ")}\r\n"
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/lib/mail/fields/message_id_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/utilities'
4 |
5 | module Mail
6 | # Only one Message-ID field may appear in a header.
7 | #
8 | # Note that parsed Message IDs do not contain their enclosing angle
9 | # brackets which, per RFC, are not part of the ID.
10 | #
11 | # mail = Mail.new
12 | # mail.message_id = '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
13 | # mail.message_id #=> '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
14 | # mail[:message_id] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
15 | # mail['message_id'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
16 | # mail['Message-ID'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
17 | #
18 | # mail[:message_id].message_id #=> 'F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom'
19 | # mail[:message_id].message_ids #=> ['F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom']
20 | class MessageIdField < CommonMessageIdField #:nodoc:
21 | NAME = 'Message-ID'
22 |
23 | def self.singular?
24 | true
25 | end
26 |
27 | def initialize(value = nil, charset = nil)
28 | value = Mail::Utilities.generate_message_id if Utilities.blank?(value)
29 | super value, charset
30 | end
31 |
32 | def message_ids
33 | [message_id]
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/lib/mail/fields/mime_version_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/utilities'
4 |
5 | module Mail
6 | class MimeVersionField < NamedStructuredField #:nodoc:
7 | NAME = 'MIME-Version'
8 |
9 | def self.singular?
10 | true
11 | end
12 |
13 | def initialize(value = nil, charset = nil)
14 | value = '1.0' if Utilities.blank?(value)
15 | super value, charset
16 | end
17 |
18 | def element
19 | @element ||= Mail::MimeVersionElement.new(value)
20 | end
21 |
22 | def version
23 | "#{element.major}.#{element.minor}"
24 | end
25 |
26 | def major
27 | element.major.to_i
28 | end
29 |
30 | def minor
31 | element.minor.to_i
32 | end
33 |
34 | def encoded
35 | "#{name}: #{version}\r\n"
36 | end
37 |
38 | def decoded
39 | version
40 | end
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/lib/mail/fields/named_structured_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | class NamedStructuredField < StructuredField #:nodoc:
6 | def initialize(value = nil, charset = nil)
7 | super self.class::NAME, value, charset
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/lib/mail/fields/named_unstructured_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | class NamedUnstructuredField < UnstructuredField #:nodoc:
6 | def initialize(value = nil, charset = nil)
7 | super self.class::NAME, value, charset
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/lib/mail/fields/optional_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # The field names of any optional-field MUST NOT be identical to any
6 | # field name specified elsewhere in this standard.
7 | #
8 | # optional-field = field-name ":" unstructured CRLF
9 | class OptionalField < UnstructuredField #:nodoc:
10 | private
11 | def do_encode
12 | "#{wrapped_value}\r\n"
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/lib/mail/fields/parameter_hash.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'mail/constants'
4 | require 'mail/indifferent_hash'
5 | require 'mail/encodings'
6 |
7 | module Mail
8 | # ParameterHash is an intelligent Hash that allows you to add
9 | # parameter values including the MIME extension paramaters that
10 | # have the name*0="blah", name*1="bleh" keys, and will just return
11 | # a single key called name="blahbleh" and do any required un-encoding
12 | # to make that happen
13 | #
14 | # Parameters are defined in RFC2045. Split keys are in RFC2231.
15 | class ParameterHash < IndifferentHash #:nodoc:
16 | def [](key_name)
17 | key_pattern = Regexp.escape(key_name.to_s)
18 | pairs = []
19 | exact = nil
20 |
21 | each do |k,v|
22 | if k =~ /^#{key_pattern}(\*|$)/i
23 | if $1 == Constants::ASTERISK
24 | pairs << [k, v]
25 | else
26 | exact = k
27 | end
28 | end
29 | end
30 |
31 | if pairs.empty? # Just dealing with a single value pair
32 | super(exact || key_name)
33 | else # Dealing with a multiple value pair or a single encoded value pair
34 | string = pairs.sort { |a,b| a.first.to_s <=> b.first.to_s }.map { |v| v.last }.join('')
35 | if mt = string.match(/([\w\-]+)?'(\w\w)?'(.*)/)
36 | string = mt[3]
37 | encoding = mt[1]
38 | else
39 | encoding = nil
40 | end
41 | Mail::Encodings.param_decode(string, encoding)
42 | end
43 | end
44 |
45 | def encoded
46 | map.sort_by { |a| a.first.to_s }.map! do |key_name, value|
47 | unless value.ascii_only?
48 | value = Mail::Encodings.param_encode(value)
49 | key_name = "#{key_name}*"
50 | end
51 | %Q{#{key_name}=#{Utilities.quote_token(value)}}
52 | end.join(";\r\n\s")
53 | end
54 |
55 | def decoded
56 | map.sort_by { |a| a.first.to_s }.map! do |key_name, value|
57 | %Q{#{key_name}=#{Utilities.quote_token(value)}}
58 | end.join("; ")
59 | end
60 | end
61 | end
62 |
--------------------------------------------------------------------------------
/lib/mail/fields/received_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # trace = [return]
6 | # 1*received
7 | #
8 | # return = "Return-Path:" path CRLF
9 | #
10 | # path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) /
11 | # obs-path
12 | #
13 | # received = "Received:" name-val-list ";" date-time CRLF
14 | #
15 | # name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)]
16 | #
17 | # name-val-pair = item-name CFWS item-value
18 | #
19 | # item-name = ALPHA *(["-"] (ALPHA / DIGIT))
20 | #
21 | # item-value = 1*angle-addr / addr-spec /
22 | # atom / domain / msg-id
23 | class ReceivedField < NamedStructuredField #:nodoc:
24 | NAME = 'Received'
25 |
26 | def element
27 | @element ||= Mail::ReceivedElement.new(value)
28 | end
29 |
30 | def date_time
31 | @datetime ||= element.date_time
32 | end
33 |
34 | def info
35 | element.info
36 | end
37 |
38 | def formatted_date
39 | if date_time.respond_to? :strftime and date_time.respond_to? :zone
40 | date_time.strftime("%a, %d %b %Y %H:%M:%S ") + date_time.zone.delete(':')
41 | end
42 | end
43 |
44 | private
45 | def do_encode
46 | if Utilities.blank?(value)
47 | "#{name}: \r\n"
48 | else
49 | "#{name}: #{info}; #{formatted_date}\r\n"
50 | end
51 | end
52 |
53 | def do_decode
54 | if Utilities.blank?(value)
55 | ""
56 | else
57 | "#{info}; #{formatted_date}"
58 | end
59 | end
60 | end
61 | end
62 |
--------------------------------------------------------------------------------
/lib/mail/fields/references_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # = References Field
6 | #
7 | # The References field inherits references StructuredField and handles the References: header
8 | # field in the email.
9 | #
10 | # Sending references to a mail message will instantiate a Mail::Field object that
11 | # has a ReferencesField as its field type. This includes all Mail::CommonAddress
12 | # module instance metods.
13 | #
14 | # Note that, the #message_ids method will return an array of message IDs without the
15 | # enclosing angle brackets which per RFC are not syntactically part of the message id.
16 | #
17 | # Only one References field can appear in a header, though it can have multiple
18 | # Message IDs.
19 | #
20 | # == Examples:
21 | #
22 | # mail = Mail.new
23 | # mail.references = '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
24 | # mail.references #=> '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
25 | # mail[:references] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ReferencesField:0x180e1c4
26 | # mail['references'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ReferencesField:0x180e1c4
27 | # mail['References'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ReferencesField:0x180e1c4
28 | #
29 | # mail[:references].message_ids #=> ['F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom']
30 | class ReferencesField < CommonMessageIdField #:nodoc:
31 | NAME = 'References'
32 |
33 | def self.singular?
34 | true
35 | end
36 |
37 | def initialize(value = nil, charset = nil)
38 | value = value.join("\r\n\s") if value.is_a?(Array)
39 | super value, charset
40 | end
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/lib/mail/fields/reply_to_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # = Reply-To Field
6 | #
7 | # The Reply-To field inherits reply-to StructuredField and handles the Reply-To: header
8 | # field in the email.
9 | #
10 | # Sending reply_to to a mail message will instantiate a Mail::Field object that
11 | # has a ReplyToField as its field type. This includes all Mail::CommonAddress
12 | # module instance metods.
13 | #
14 | # Only one Reply-To field can appear in a header, though it can have multiple
15 | # addresses and groups of addresses.
16 | #
17 | # == Examples:
18 | #
19 | # mail = Mail.new
20 | # mail.reply_to = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
21 | # mail.reply_to #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
22 | # mail[:reply_to] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ReplyToField:0x180e1c4
23 | # mail['reply-to'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ReplyToField:0x180e1c4
24 | # mail['Reply-To'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ReplyToField:0x180e1c4
25 | #
26 | # mail[:reply_to].encoded #=> 'Reply-To: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
27 | # mail[:reply_to].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
28 | # mail[:reply_to].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
29 | # mail[:reply_to].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
30 | class ReplyToField < CommonAddressField #:nodoc:
31 | NAME = 'Reply-To'
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/lib/mail/fields/resent_bcc_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # = Resent-Bcc Field
6 | #
7 | # The Resent-Bcc field inherits resent-bcc StructuredField and handles the
8 | # Resent-Bcc: header field in the email.
9 | #
10 | # Sending resent_bcc to a mail message will instantiate a Mail::Field object that
11 | # has a ResentBccField as its field type. This includes all Mail::CommonAddress
12 | # module instance metods.
13 | #
14 | # Only one Resent-Bcc field can appear in a header, though it can have multiple
15 | # addresses and groups of addresses.
16 | #
17 | # == Examples:
18 | #
19 | # mail = Mail.new
20 | # mail.resent_bcc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
21 | # mail.resent_bcc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
22 | # mail[:resent_bcc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentBccField:0x180e1c4
23 | # mail['resent-bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentBccField:0x180e1c4
24 | # mail['Resent-Bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentBccField:0x180e1c4
25 | #
26 | # mail[:resent_bcc].encoded #=> 'Resent-Bcc: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
27 | # mail[:resent_bcc].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
28 | # mail[:resent_bcc].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
29 | # mail[:resent_bcc].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
30 | class ResentBccField < CommonAddressField #:nodoc:
31 | NAME = 'Resent-Bcc'
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/lib/mail/fields/resent_cc_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # = Resent-Cc Field
6 | #
7 | # The Resent-Cc field inherits resent-cc StructuredField and handles the Resent-Cc: header
8 | # field in the email.
9 | #
10 | # Sending resent_cc to a mail message will instantiate a Mail::Field object that
11 | # has a ResentCcField as its field type. This includes all Mail::CommonAddress
12 | # module instance metods.
13 | #
14 | # Only one Resent-Cc field can appear in a header, though it can have multiple
15 | # addresses and groups of addresses.
16 | #
17 | # == Examples:
18 | #
19 | # mail = Mail.new
20 | # mail.resent_cc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
21 | # mail.resent_cc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
22 | # mail[:resent_cc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentCcField:0x180e1c4
23 | # mail['resent-cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentCcField:0x180e1c4
24 | # mail['Resent-Cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentCcField:0x180e1c4
25 | #
26 | # mail[:resent_cc].encoded #=> 'Resent-Cc: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
27 | # mail[:resent_cc].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
28 | # mail[:resent_cc].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
29 | # mail[:resent_cc].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
30 | class ResentCcField < CommonAddressField #:nodoc:
31 | NAME = 'Resent-Cc'
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/lib/mail/fields/resent_date_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | #
6 | # resent-date = "Resent-Date:" date-time CRLF
7 | class ResentDateField < CommonDateField #:nodoc:
8 | NAME = 'Resent-Date'
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/lib/mail/fields/resent_from_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # = Resent-From Field
6 | #
7 | # The Resent-From field inherits resent-from StructuredField and handles the Resent-From: header
8 | # field in the email.
9 | #
10 | # Sending resent_from to a mail message will instantiate a Mail::Field object that
11 | # has a ResentFromField as its field type. This includes all Mail::CommonAddress
12 | # module instance metods.
13 | #
14 | # Only one Resent-From field can appear in a header, though it can have multiple
15 | # addresses and groups of addresses.
16 | #
17 | # == Examples:
18 | #
19 | # mail = Mail.new
20 | # mail.resent_from = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
21 | # mail.resent_from #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
22 | # mail[:resent_from] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentFromField:0x180e1c4
23 | # mail['resent-from'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentFromField:0x180e1c4
24 | # mail['Resent-From'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentFromField:0x180e1c4
25 | #
26 | # mail[:resent_from].encoded #=> 'Resent-From: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
27 | # mail[:resent_from].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
28 | # mail[:resent_from].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
29 | # mail[:resent_from].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
30 | class ResentFromField < CommonAddressField #:nodoc:
31 | NAME = 'Resent-From'
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/lib/mail/fields/resent_message_id_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | #
6 | # resent-msg-id = "Resent-Message-ID:" msg-id CRLF
7 | class ResentMessageIdField < CommonMessageIdField #:nodoc:
8 | NAME = 'Resent-Message-ID'
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/lib/mail/fields/resent_sender_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # = Resent-Sender Field
6 | #
7 | # The Resent-Sender field inherits resent-sender StructuredField and handles the Resent-Sender: header
8 | # field in the email.
9 | #
10 | # Sending resent_sender to a mail message will instantiate a Mail::Field object that
11 | # has a ResentSenderField as its field type. This includes all Mail::CommonAddress
12 | # module instance metods.
13 | #
14 | # Only one Resent-Sender field can appear in a header, though it can have multiple
15 | # addresses and groups of addresses.
16 | #
17 | # == Examples:
18 | #
19 | # mail = Mail.new
20 | # mail.resent_sender = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
21 | # mail.resent_sender #=> ['mikel@test.lindsaar.net']
22 | # mail[:resent_sender] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentSenderField:0x180e1c4
23 | # mail['resent-sender'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentSenderField:0x180e1c4
24 | # mail['Resent-Sender'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentSenderField:0x180e1c4
25 | #
26 | # mail.resent_sender.to_s #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
27 | # mail.resent_sender.addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
28 | # mail.resent_sender.formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
29 | class ResentSenderField < CommonAddressField #:nodoc:
30 | NAME = 'Resent-Sender'
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/lib/mail/fields/resent_to_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # = Resent-To Field
6 | #
7 | # The Resent-To field inherits resent-to StructuredField and handles the Resent-To: header
8 | # field in the email.
9 | #
10 | # Sending resent_to to a mail message will instantiate a Mail::Field object that
11 | # has a ResentToField as its field type. This includes all Mail::CommonAddress
12 | # module instance metods.
13 | #
14 | # Only one Resent-To field can appear in a header, though it can have multiple
15 | # addresses and groups of addresses.
16 | #
17 | # == Examples:
18 | #
19 | # mail = Mail.new
20 | # mail.resent_to = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
21 | # mail.resent_to #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
22 | # mail[:resent_to] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentToField:0x180e1c4
23 | # mail['resent-to'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentToField:0x180e1c4
24 | # mail['Resent-To'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentToField:0x180e1c4
25 | #
26 | # mail[:resent_to].encoded #=> 'Resent-To: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
27 | # mail[:resent_to].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
28 | # mail[:resent_to].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
29 | # mail[:resent_to].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
30 | class ResentToField < CommonAddressField #:nodoc:
31 | NAME = 'Resent-To'
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/lib/mail/fields/return_path_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # 4.4.3. REPLY-TO / RESENT-REPLY-TO
6 | #
7 | # Note: The "Return-Path" field is added by the mail transport
8 | # service, at the time of final deliver. It is intended
9 | # to identify a path back to the orginator of the mes-
10 | # sage. The "Reply-To" field is added by the message
11 | # originator and is intended to direct replies.
12 | #
13 | # trace = [return]
14 | # 1*received
15 | #
16 | # return = "Return-Path:" path CRLF
17 | #
18 | # path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) /
19 | # obs-path
20 | #
21 | # received = "Received:" name-val-list ";" date-time CRLF
22 | #
23 | # name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)]
24 | #
25 | # name-val-pair = item-name CFWS item-value
26 | #
27 | # item-name = ALPHA *(["-"] (ALPHA / DIGIT))
28 | #
29 | # item-value = 1*angle-addr / addr-spec /
30 | # atom / domain / msg-id
31 | #
32 | class ReturnPathField < CommonAddressField #:nodoc:
33 | NAME = 'Return-Path'
34 |
35 | def self.singular?
36 | true
37 | end
38 |
39 | def initialize(value = nil, charset = nil)
40 | if value == '<>'
41 | super nil, charset
42 | else
43 | super
44 | end
45 | end
46 |
47 | def default
48 | address
49 | end
50 |
51 | private
52 | def do_encode
53 | "#{name}: <#{address}>\r\n"
54 | end
55 |
56 | def do_decode
57 | address
58 | end
59 | end
60 | end
61 |
--------------------------------------------------------------------------------
/lib/mail/fields/sender_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # = Sender Field
6 | #
7 | # The Sender field inherits sender StructuredField and handles the Sender: header
8 | # field in the email.
9 | #
10 | # Sending sender to a mail message will instantiate a Mail::Field object that
11 | # has a SenderField as its field type. This includes all Mail::CommonAddress
12 | # module instance metods.
13 | #
14 | # Only one Sender field can appear in a header, though it can have multiple
15 | # addresses and groups of addresses.
16 | #
17 | # == Examples:
18 | #
19 | # mail = Mail.new
20 | # mail.sender = 'Mikel Lindsaar <mikel@test.lindsaar.net>'
21 | # mail.sender #=> 'mikel@test.lindsaar.net'
22 | # mail[:sender] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::SenderField:0x180e1c4
23 | # mail['sender'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::SenderField:0x180e1c4
24 | # mail['Sender'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::SenderField:0x180e1c4
25 | #
26 | # mail[:sender].encoded #=> "Sender: Mikel Lindsaar <mikel@test.lindsaar.net>\r\n"
27 | # mail[:sender].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>'
28 | # mail[:sender].addresses #=> ['mikel@test.lindsaar.net']
29 | # mail[:sender].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>']
30 | class SenderField < CommonAddressField #:nodoc:
31 | NAME = 'Sender'
32 |
33 | def self.singular?
34 | true
35 | end
36 |
37 | def default
38 | address
39 | end
40 |
41 | def addresses
42 | Array(super.first)
43 | end
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/lib/mail/fields/structured_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # Provides access to a structured header field
6 | #
7 | # ===Per RFC 2822:
8 | # 2.2.2. Structured Header Field Bodies
9 | #
10 | # Some field bodies in this standard have specific syntactical
11 | # structure more restrictive than the unstructured field bodies
12 | # described above. These are referred to as "structured" field bodies.
13 | # Structured field bodies are sequences of specific lexical tokens as
14 | # described in sections 3 and 4 of this standard. Many of these tokens
15 | # are allowed (according to their syntax) to be introduced or end with
16 | # comments (as described in section 3.2.3) as well as the space (SP,
17 | # ASCII value 32) and horizontal tab (HTAB, ASCII value 9) characters
18 | # (together known as the white space characters, WSP), and those WSP
19 | # characters are subject to header "folding" and "unfolding" as
20 | # described in section 2.2.3. Semantic analysis of structured field
21 | # bodies is given along with their syntax.
22 | class StructuredField < CommonField #:nodoc:
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/lib/mail/fields/subject_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | #
6 | # subject = "Subject:" unstructured CRLF
7 | class SubjectField < NamedUnstructuredField #:nodoc:
8 | NAME = 'Subject'
9 |
10 | def self.singular?
11 | true
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/lib/mail/fields/to_field.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 | # = To Field
6 | #
7 | # The To field inherits to StructuredField and handles the To: header
8 | # field in the email.
9 | #
10 | # Sending to to a mail message will instantiate a Mail::Field object that
11 | # has a ToField as its field type. This includes all Mail::CommonAddress
12 | # module instance metods.
13 | #
14 | # Only one To field can appear in a header, though it can have multiple
15 | # addresses and groups of addresses.
16 | #
17 | # == Examples:
18 | #
19 | # mail = Mail.new
20 | # mail.to = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
21 | # mail.to #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
22 | # mail[:to] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ToField:0x180e1c4
23 | # mail['to'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ToField:0x180e1c4
24 | # mail['To'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ToField:0x180e1c4
25 | #
26 | # mail[:to].encoded #=> 'To: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
27 | # mail[:to].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
28 | # mail[:to].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
29 | # mail[:to].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
30 | class ToField < CommonAddressField #:nodoc:
31 | NAME = 'To'
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/lib/mail/matchers/attachment_matchers.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module Mail
3 | module Matchers
4 | def any_attachment
5 | AnyAttachmentMatcher.new
6 | end
7 |
8 | def an_attachment_with_filename(filename)
9 | AttachmentFilenameMatcher.new(filename)
10 | end
11 |
12 | def an_attachment_with_mime_type(filename)
13 | AttachmentMimeTypeMatcher.new(filename)
14 | end
15 |
16 | class AnyAttachmentMatcher
17 | def ===(other)
18 | other.attachment?
19 | end
20 | end
21 |
22 | class AttachmentFilenameMatcher
23 | attr_reader :filename
24 | def initialize(filename)
25 | @filename = filename
26 | end
27 |
28 | def ===(other)
29 | other.attachment? && other.filename == filename
30 | end
31 | end
32 |
33 | class AttachmentMimeTypeMatcher
34 | attr_reader :mime_type
35 | def initialize(mime_type)
36 | @mime_type = mime_type
37 | end
38 |
39 | def ===(other)
40 | other.attachment? && other.mime_type == mime_type
41 | end
42 | end
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/lib/mail/multibyte/utils.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail #:nodoc:
5 | module Multibyte #:nodoc:
6 | # Returns a regular expression that matches valid characters in the current encoding
7 | def self.valid_character
8 | VALID_CHARACTER[Encoding.default_external.to_s]
9 | end
10 |
11 | # Returns true if string has valid utf-8 encoding
12 | def self.is_utf8?(string)
13 | case string.encoding
14 | when Encoding::UTF_8
15 | verify(string)
16 | when Encoding::ASCII_8BIT, Encoding::US_ASCII
17 | verify(to_utf8(string))
18 | else
19 | false
20 | end
21 | end
22 |
23 | # Verifies the encoding of a string
24 | def self.verify(string)
25 | string.valid_encoding?
26 | end
27 |
28 | # Verifies the encoding of the string and raises an exception when it's not valid
29 | def self.verify!(string)
30 | raise EncodingError.new("Found characters with invalid encoding") unless verify(string)
31 | end
32 |
33 | # Removes all invalid characters from the string.
34 | #
35 | # Note: this method is a no-op in Ruby 1.9
36 | def self.clean(string)
37 | string
38 | end
39 |
40 | def self.to_utf8(string)
41 | string.dup.force_encoding(Encoding::UTF_8)
42 | end
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/lib/mail/network.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'mail/network/retriever_methods/base'
3 |
4 | module Mail
5 | register_autoload :SMTP, 'mail/network/delivery_methods/smtp'
6 | register_autoload :FileDelivery, 'mail/network/delivery_methods/file_delivery'
7 | register_autoload :LoggerDelivery, 'mail/network/delivery_methods/logger_delivery'
8 | register_autoload :Sendmail, 'mail/network/delivery_methods/sendmail'
9 | register_autoload :Exim, 'mail/network/delivery_methods/exim'
10 | register_autoload :SMTPConnection, 'mail/network/delivery_methods/smtp_connection'
11 | register_autoload :TestMailer, 'mail/network/delivery_methods/test_mailer'
12 |
13 | register_autoload :POP3, 'mail/network/retriever_methods/pop3'
14 | register_autoload :IMAP, 'mail/network/retriever_methods/imap'
15 | register_autoload :TestRetriever, 'mail/network/retriever_methods/test_retriever'
16 | end
17 |
--------------------------------------------------------------------------------
/lib/mail/network/delivery_methods/exim.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Mail
4 | # A delivery method implementation which sends via exim.
5 | #
6 | # To use this, first find out where the exim binary is on your computer,
7 | # if you are on a mac or unix box, it is usually in /usr/sbin/exim, this will
8 | # be your exim location.
9 | #
10 | # Mail.defaults do
11 | # delivery_method :exim
12 | # end
13 | #
14 | # Or if your exim binary is not at '/usr/sbin/exim'
15 | #
16 | # Mail.defaults do
17 | # delivery_method :exim, :location => '/absolute/path/to/your/exim'
18 | # end
19 | #
20 | # Then just deliver the email as normal:
21 | #
22 | # Mail.deliver do
23 | # to 'mikel@test.lindsaar.net'
24 | # from 'ada@test.lindsaar.net'
25 | # subject 'testing exim'
26 | # body 'testing exim'
27 | # end
28 | #
29 | # Or by calling deliver on a Mail message
30 | #
31 | # mail = Mail.new do
32 | # to 'mikel@test.lindsaar.net'
33 | # from 'ada@test.lindsaar.net'
34 | # subject 'testing exim'
35 | # body 'testing exim'
36 | # end
37 | #
38 | # mail.deliver!
39 | class Exim < Sendmail
40 | DEFAULTS = {
41 | :location => '/usr/sbin/exim',
42 | :arguments => %w[ -i -t ]
43 | }
44 |
45 | # Uses -t option to extract recipients from the message.
46 | def destinations_for(envelope)
47 | nil
48 | end
49 | end
50 | end
51 |
--------------------------------------------------------------------------------
/lib/mail/network/delivery_methods/file_delivery.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'mail/smtp_envelope'
3 |
4 | module Mail
5 | # FileDelivery class delivers emails into multiple files based on the destination
6 | # address. Each file is appended to if it already exists.
7 | #
8 | # So if you have an email going to fred@test, bob@test, joe@anothertest, and you
9 | # set your location path to /path/to/mails then FileDelivery will create the directory
10 | # if it does not exist, and put one copy of the email in three files, called
11 | # by their message id
12 | #
13 | # Make sure the path you specify with :location is writable by the Ruby process
14 | # running Mail.
15 | class FileDelivery
16 | require 'fileutils'
17 |
18 | attr_accessor :settings
19 |
20 | def initialize(values)
21 | self.settings = { :location => './mails', :extension => '' }.merge!(values)
22 | end
23 |
24 | def deliver!(mail)
25 | envelope = Mail::SmtpEnvelope.new(mail)
26 |
27 | if ::File.respond_to?(:makedirs)
28 | ::File.makedirs settings[:location]
29 | else
30 | ::FileUtils.mkdir_p settings[:location]
31 | end
32 |
33 | envelope.to.uniq.each do |to|
34 | path = ::File.join(settings[:location], File.basename(to.to_s+settings[:extension]))
35 |
36 | ::File.open(path, 'a') do |f|
37 | f.write envelope.message
38 | f.write "\r\n\r\n"
39 | end
40 | end
41 | end
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/lib/mail/network/delivery_methods/logger_delivery.rb:
--------------------------------------------------------------------------------
1 | require 'mail/smtp_envelope'
2 |
3 | module Mail
4 | class LoggerDelivery
5 | attr_reader :logger, :severity, :settings
6 |
7 | def initialize(settings)
8 | @settings = settings
9 | @logger = settings.fetch(:logger) { default_logger }
10 | @severity = derive_severity(settings[:severity])
11 | end
12 |
13 | def deliver!(mail)
14 | logger.log(severity) { Mail::SmtpEnvelope.new(mail).message }
15 | end
16 |
17 | private
18 | def default_logger
19 | require 'logger'
20 | ::Logger.new($stdout)
21 | end
22 |
23 | def derive_severity(severity)
24 | case severity
25 | when nil
26 | Logger::INFO
27 | when Integer
28 | severity
29 | else
30 | Logger.const_get(severity.to_s.upcase)
31 | end
32 | end
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/lib/mail/network/delivery_methods/smtp_connection.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'mail/smtp_envelope'
3 |
4 | module Mail
5 | # == Sending Email with SMTP
6 | #
7 | # Mail allows you to send emails using an open SMTP connection. This is done by
8 | # passing a created Net::SMTP object. This way we can get better performance to
9 | # our local mail server by reducing the number of connections at any one time.
10 | #
11 | # === Sending via SMTP server on Localhost
12 | #
13 | # To send mail open a connection with Net::Smtp using any options you like
14 | # === Delivering the email
15 | #
16 | # Once you have the settings right, sending the email is done by:
17 | #
18 | # smtp_conn = Net::SMTP.start(settings[:address], settings[:port])
19 | # Mail.defaults do
20 | # delivery_method :smtp_connection, { :connection => smtp_conn }
21 | # end
22 | #
23 | # Mail.deliver do
24 | # to 'mikel@test.lindsaar.net'
25 | # from 'ada@test.lindsaar.net'
26 | # subject 'testing sendmail'
27 | # body 'testing sendmail'
28 | # end
29 | #
30 | # Or by calling deliver on a Mail message
31 | #
32 | # mail = Mail.new do
33 | # to 'mikel@test.lindsaar.net'
34 | # from 'ada@test.lindsaar.net'
35 | # subject 'testing sendmail'
36 | # body 'testing sendmail'
37 | # end
38 | #
39 | # mail.deliver!
40 | class SMTPConnection
41 | attr_accessor :smtp, :settings
42 |
43 | def initialize(values)
44 | raise ArgumentError.new('A Net::SMTP object is required for this delivery method') if values[:connection].nil?
45 | self.smtp = values[:connection]
46 | self.settings = values
47 | end
48 |
49 | # Send the message via SMTP.
50 | # The from and to attributes are optional. If not set, they are retrieve from the Message.
51 | def deliver!(mail)
52 | envelope = Mail::SmtpEnvelope.new(mail)
53 | response = smtp.sendmail(envelope.message, envelope.from, envelope.to)
54 | settings[:return_response] ? response : self
55 | end
56 | end
57 | end
58 |
--------------------------------------------------------------------------------
/lib/mail/network/delivery_methods/test_mailer.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'mail/smtp_envelope'
3 |
4 | module Mail
5 | # The TestMailer is a bare bones mailer that does nothing. It is useful
6 | # when you are testing.
7 | #
8 | # It also provides a template of the minimum methods you require to implement
9 | # if you want to make a custom mailer for Mail
10 | class TestMailer
11 | # Provides a store of all the emails sent with the TestMailer so you can check them.
12 | def self.deliveries
13 | @@deliveries ||= []
14 | end
15 |
16 | # Allows you to over write the default deliveries store from an array to some
17 | # other object. If you just want to clear the store,
18 | # call TestMailer.deliveries.clear.
19 | #
20 | # If you place another object here, please make sure it responds to:
21 | #
22 | # * << (message)
23 | # * clear
24 | # * length
25 | # * size
26 | # * and other common Array methods
27 | def self.deliveries=(val)
28 | @@deliveries = val
29 | end
30 |
31 | attr_accessor :settings
32 |
33 | def initialize(values)
34 | @settings = values.dup
35 | end
36 |
37 | def deliver!(mail)
38 | # Create the envelope to validate it
39 | Mail::SmtpEnvelope.new(mail)
40 |
41 | Mail::TestMailer.deliveries << mail
42 | end
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/lib/mail/network/retriever_methods/test_retriever.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | module Mail
5 |
6 | class TestRetriever < Retriever
7 |
8 | def self.emails
9 | @@emails
10 | end
11 |
12 | def self.emails=(val)
13 | @@emails = val
14 | end
15 |
16 | def initialize(values)
17 | @@emails = []
18 | end
19 |
20 | def find(options = nil, &block)
21 | options = options ? Hash[options] : {}
22 | options[:count] ||= :all
23 | options[:order] ||= :asc
24 | options[:what] ||= :first
25 | emails_index = (0...@@emails.size).to_a
26 | emails_index.reverse! if options[:what] == :last
27 | emails_index = case count = options[:count]
28 | when :all then emails_index
29 | when Integer then emails_index[0, count]
30 | else
31 | raise 'Invalid count option value: ' + count.inspect
32 | end
33 | if options[:what] == :last && options[:order] == :asc || options[:what] == :first && options[:order] == :desc
34 | emails_index.reverse!
35 | end
36 | emails_index.each { |idx| @@emails[idx].mark_for_delete = true } if options[:delete_after_find]
37 | emails = emails_index.map { |idx| @@emails[idx] }
38 | emails.each { |email| yield email } if block_given?
39 | @@emails.reject!(&:is_marked_for_delete?) if options[:delete_after_find]
40 | emails.size == 1 && options[:count] == 1 ? emails.first : emails
41 | end
42 |
43 | end
44 |
45 | end
46 |
--------------------------------------------------------------------------------
/lib/mail/parser_tools.rb:
--------------------------------------------------------------------------------
1 | module Mail
2 | # Extends each field parser with utility methods.
3 | module ParserTools #:nodoc:
4 | # Slice bytes from ASCII-8BIT data and mark as UTF-8.
5 | if 'string'.respond_to?(:force_encoding)
6 | def chars(data, from_bytes, to_bytes)
7 | data.slice(from_bytes..to_bytes).force_encoding(Encoding::UTF_8)
8 | end
9 | else
10 | def chars(data, from_bytes, to_bytes)
11 | data.slice(from_bytes..to_bytes)
12 | end
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/lib/mail/parsers.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'mail/parsers/address_lists_parser'
4 | require 'mail/parsers/content_disposition_parser'
5 | require 'mail/parsers/content_location_parser'
6 | require 'mail/parsers/content_transfer_encoding_parser'
7 | require 'mail/parsers/content_type_parser'
8 | require 'mail/parsers/date_time_parser'
9 | require 'mail/parsers/envelope_from_parser'
10 | require 'mail/parsers/message_ids_parser'
11 | require 'mail/parsers/mime_version_parser'
12 | require 'mail/parsers/phrase_lists_parser'
13 | require 'mail/parsers/received_parser'
14 |
--------------------------------------------------------------------------------
/lib/mail/parsers/content_transfer_encoding_parser.rl:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'mail/utilities'
3 | require 'mail/parser_tools'
4 |
5 | begin
6 | original_verbose, $VERBOSE = $VERBOSE, nil
7 |
8 | %%{
9 | machine content_transfer_encoding;
10 | alphtype int;
11 |
12 | action encoding_s { encoding_s = p }
13 | action encoding_e { content_transfer_encoding.encoding = chars(data, encoding_s, p-1).downcase }
14 |
15 | # No-op actions
16 | action comment_e { }
17 | action comment_s { }
18 | action phrase_e { }
19 | action phrase_s { }
20 | action qstr_e { }
21 | action qstr_s { }
22 | action param_attr_e { }
23 | action param_attr_s { }
24 | action param_val_e { }
25 | action param_val_s { }
26 | action main_type_e { }
27 | action main_type_s { }
28 | action sub_type_e { }
29 | action sub_type_s { }
30 |
31 | include rfc2045_content_transfer_encoding "rfc2045_content_transfer_encoding.rl";
32 | main := content_transfer_encoding;
33 | }%%
34 |
35 | module Mail::Parsers
36 | module ContentTransferEncodingParser
37 | extend Mail::ParserTools
38 |
39 | ContentTransferEncodingStruct = Struct.new(:encoding, :error)
40 |
41 | %%write data noprefix;
42 |
43 | def self.parse(data)
44 | data = data.dup.force_encoding(Encoding::ASCII_8BIT) if data.respond_to?(:force_encoding)
45 |
46 | content_transfer_encoding = ContentTransferEncodingStruct.new('')
47 | return content_transfer_encoding if Mail::Utilities.blank?(data)
48 |
49 | # Parser state
50 | encoding_s = nil
51 |
52 | # 5.1 Variables Used by Ragel
53 | p = 0
54 | eof = pe = data.length
55 | stack = []
56 |
57 | %%write init;
58 | %%write exec;
59 |
60 | if false
61 | testEof
62 | end
63 |
64 | if p != eof || cs < %%{ write first_final; }%%
65 | raise Mail::Field::IncompleteParseError.new(Mail::ContentTransferEncodingElement, data, p)
66 | end
67 |
68 | content_transfer_encoding
69 | end
70 | end
71 | end
72 |
73 | ensure
74 | $VERBOSE = original_verbose
75 | end
76 |
--------------------------------------------------------------------------------
/lib/mail/parsers/date_time_parser.rl:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'mail/utilities'
3 | require 'mail/parser_tools'
4 |
5 | begin
6 | original_verbose, $VERBOSE = $VERBOSE, nil
7 |
8 | %%{
9 | machine date_time;
10 | alphtype int;
11 |
12 | # Date
13 | action date_s { date_s = p }
14 | action date_e { date_time.date_string = chars(data, date_s, p-1) }
15 |
16 | # Time
17 | action time_s { time_s = p }
18 | action time_e { date_time.time_string = chars(data, time_s, p-1) }
19 |
20 | # No-op actions
21 | action comment_s {}
22 | action comment_e {}
23 | action phrase_s {}
24 | action phrase_e {}
25 | action qstr_s {}
26 | action qstr_e {}
27 |
28 | include rfc5322_date_time "rfc5322_date_time.rl";
29 | main := date_time;
30 | }%%
31 |
32 | module Mail::Parsers
33 | module DateTimeParser
34 | extend Mail::ParserTools
35 |
36 | DateTimeStruct = Struct.new(:date_string, :time_string, :error)
37 |
38 | %%write data noprefix;
39 |
40 | def self.parse(data)
41 | data = data.dup.force_encoding(Encoding::ASCII_8BIT) if data.respond_to?(:force_encoding)
42 |
43 | raise Mail::Field::NilParseError.new(Mail::DateTimeElement) if data.nil?
44 |
45 | date_time = DateTimeStruct.new([])
46 |
47 | # Parser state
48 | date_s = time_s = nil
49 |
50 | # 5.1 Variables Used by Ragel
51 | p = 0
52 | eof = pe = data.length
53 | stack = []
54 |
55 | %%write init;
56 | %%write exec;
57 |
58 | if false
59 | testEof
60 | end
61 |
62 | if p != eof || cs < %%{ write first_final; }%%
63 | raise Mail::Field::IncompleteParseError.new(Mail::DateTimeElement, data, p)
64 | end
65 |
66 | date_time
67 | end
68 | end
69 | end
70 |
71 | ensure
72 | $VERBOSE = original_verbose
73 | end
74 |
--------------------------------------------------------------------------------
/lib/mail/parsers/mime_version_parser.rl:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'mail/utilities'
3 | require 'mail/parser_tools'
4 |
5 | begin
6 | original_verbose, $VERBOSE = $VERBOSE, nil
7 |
8 | %%{
9 | machine mime_version;
10 | alphtype int;
11 |
12 | # Major Digits
13 | action major_digits_s { major_digits_s = p }
14 | action major_digits_e { mime_version.major = chars(data, major_digits_s, p-1) }
15 |
16 | # Minor Digits
17 | action minor_digits_s { minor_digits_s = p }
18 | action minor_digits_e { mime_version.minor = chars(data, minor_digits_s, p-1) }
19 |
20 | # No-op actions
21 | action comment_s {}
22 | action comment_e {}
23 | action qstr_s {}
24 | action qstr_e {}
25 | action phrase_s {}
26 | action phrase_e {}
27 |
28 | include rfc2045_mime "rfc2045_mime.rl";
29 | main := mime_version;
30 | }%%
31 |
32 | module Mail::Parsers
33 | module MimeVersionParser
34 | extend Mail::ParserTools
35 |
36 | MimeVersionStruct = Struct.new(:major, :minor, :error)
37 |
38 | %%write data noprefix;
39 |
40 | def self.parse(data)
41 | data = data.dup.force_encoding(Encoding::ASCII_8BIT) if data.respond_to?(:force_encoding)
42 |
43 | return MimeVersionStruct.new('', nil) if Mail::Utilities.blank?(data)
44 |
45 | # Parser state
46 | mime_version = MimeVersionStruct.new
47 | major_digits_s = minor_digits_s = nil
48 |
49 | # 5.1 Variables Used by Ragel
50 | p = 0
51 | eof = pe = data.length
52 | stack = []
53 |
54 | %%write init;
55 | %%write exec;
56 |
57 | if false
58 | testEof
59 | end
60 |
61 | if p != eof || cs < %%{ write first_final; }%%
62 | raise Mail::Field::IncompleteParseError.new(Mail::MimeVersionElement, data, p)
63 | end
64 |
65 | mime_version
66 | end
67 | end
68 | end
69 |
70 | ensure
71 | $VERBOSE = original_verbose
72 | end
73 |
--------------------------------------------------------------------------------
/lib/mail/parsers/rfc2045_content_transfer_encoding.rl:
--------------------------------------------------------------------------------
1 | %%{
2 | # RFC 2045 Section 6.1: Content-Transfer-Encoding Header Field
3 | # https://tools.ietf.org/html/rfc2045#section-6.1
4 | machine rfc2045_content_transfer_encoding;
5 | alphtype int;
6 |
7 | include rfc2045_content_type "rfc2045_content_type.rl";
8 |
9 | encoding = ('7bits' | '8bits' | '7bit' | '8bit' | 'binary' |
10 | 'quoted-printable' | 'base64' | ietf_token |
11 | custom_x_token) >encoding_s %encoding_e;
12 | content_transfer_encoding = CFWS? encoding CFWS? ";"? CFWS?;
13 | }%%
14 |
--------------------------------------------------------------------------------
/lib/mail/parsers/rfc2045_content_type.rl:
--------------------------------------------------------------------------------
1 | %%{
2 | # RFC 2045 Section 5.1: Content-Type Header Field
3 | # https://tools.ietf.org/html/rfc2045#section-5.1
4 | # Previously: https://tools.ietf.org/html/rfc1049#section-3
5 | machine rfc2045_content_type;
6 | alphtype int;
7 |
8 | include rfc5322_lexical_tokens "rfc5322_lexical_tokens.rl";
9 |
10 | token = 0x21..0x27 | 0x2a..0x2b | 0x2c..0x2e | 0x30..0x39 | 0x41..0x5a | 0x5e..0x7e;
11 | value = (quoted_string | (token -- '"' | 0x3d)+) >param_val_s %param_val_e;
12 | attribute = (token+) >param_attr_s %param_attr_e;
13 | parameter = CFWS? attribute "=" value CFWS?;
14 |
15 | ietf_token = token+;
16 | custom_x_token = 'x'i "-" token+;
17 | extension_token = ietf_token | custom_x_token;
18 | discrete_type = 'text'i | 'image'i | 'audio'i | 'video'i |
19 | 'application'i | extension_token;
20 | composite_type = 'message'i | 'multipart'i | extension_token;
21 | iana_token = token+;
22 | main_type = (discrete_type | composite_type) >main_type_s %main_type_e;
23 | sub_type = (extension_token | iana_token) >sub_type_s %sub_type_e;
24 | content_type = main_type "/" sub_type (((CFWS? ";"+) | CFWS) parameter CFWS?)*;
25 | }%%
26 |
--------------------------------------------------------------------------------
/lib/mail/parsers/rfc2045_mime.rl:
--------------------------------------------------------------------------------
1 | %%{
2 | # RFC 2045 MIME
3 | # https://tools.ietf.org/html/rfc2045
4 | machine rfc2045_mime;
5 | alphtype int;
6 |
7 | include rfc5322_lexical_tokens "rfc5322_lexical_tokens.rl";
8 |
9 | # 4. MIME-Version Header Field
10 | # https://tools.ietf.org/html/rfc2045#section-4
11 | mime_version = CFWS?
12 | (DIGIT+ >major_digits_s %major_digits_e)
13 | comment? "." comment?
14 | (DIGIT+ >minor_digits_s %minor_digits_e)
15 | CFWS?;
16 | }%%
17 |
--------------------------------------------------------------------------------
/lib/mail/parsers/rfc2183_content_disposition.rl:
--------------------------------------------------------------------------------
1 | %%{
2 | # RFC 2183 The Content-Disposition Header Field
3 | # https://tools.ietf.org/html/rfc2183#section-2
4 | #
5 | # TODO: recognize filename, size, creation date, etc.
6 | machine rfc2183_content_disposition;
7 | alphtype int;
8 |
9 | include rfc2045_content_type "rfc2045_content_type.rl";
10 |
11 | disposition_type = 'inline'i | 'attachment'i | extension_token;
12 | disposition_parm = parameter;
13 | disposition = (disposition_type >disp_type_s %disp_type_e)
14 | (";" disposition_parm)*;
15 | }%%
16 |
--------------------------------------------------------------------------------
/lib/mail/parsers/rfc3629_utf8.rl:
--------------------------------------------------------------------------------
1 | %%{
2 | # RFC 3629 4. Syntax of UTF-8 Byte Sequences
3 | # https://tools.ietf.org/html/rfc3629#section-4
4 | machine rfc3629_utf8;
5 | alphtype int;
6 |
7 | utf8_tail = 0x80..0xBF;
8 |
9 | utf8_2byte = 0xC2..0xDF utf8_tail;
10 | utf8_3byte = 0xE0 0xA0..0xBF utf8_tail |
11 | 0xE1..0xEC utf8_tail utf8_tail |
12 | 0xED 0x80..0x9F utf8_tail |
13 | 0xEE..0xEF utf8_tail utf8_tail;
14 | utf8_4byte = 0xF0 0x90..0xBF utf8_tail utf8_tail |
15 | 0xF1..0xF3 utf8_tail utf8_tail utf8_tail |
16 | 0xF4 0x80..0x8F utf8_tail utf8_tail;
17 |
18 | utf8_non_ascii = utf8_2byte | utf8_3byte | utf8_4byte;
19 | }%%
20 |
--------------------------------------------------------------------------------
/lib/mail/parsers/rfc5234_abnf_core_rules.rl:
--------------------------------------------------------------------------------
1 | %%{
2 | # RFC 5234 B.1. Core Rules
3 | # https://tools.ietf.org/html/rfc5234#appendix-B.1
4 | machine rfc5234_abnf_core_rules;
5 | alphtype int;
6 |
7 | include rfc3629_utf8 "rfc3629_utf8.rl";
8 |
9 | LF = "\n";
10 | CR = "\r";
11 | CRLF = "\r\n";
12 | SP = " ";
13 | HTAB = "\t";
14 | WSP = SP | HTAB;
15 | DQUOTE = '"';
16 | DIGIT = [0-9];
17 | ALPHA = [a-zA-Z];
18 |
19 | # RFC6532 extension for UTF-8 content
20 | rfc5234_VCHAR = 0x21..0x7e;
21 | VCHAR = rfc5234_VCHAR | utf8_non_ascii;
22 | }%%
23 |
--------------------------------------------------------------------------------
/lib/mail/parsers/rfc5322_date_time.rl:
--------------------------------------------------------------------------------
1 | %%{
2 | # RFC 5322 Internet Message Format
3 | # Section 3.3. Date and Time Specification
4 | # https://tools.ietf.org/html/rfc5322#section-3.3
5 | machine rfc5322_date_time;
6 | alphtype int;
7 |
8 | include rfc5322_lexical_tokens "rfc5322_lexical_tokens.rl";
9 |
10 | # day_of_week
11 | day_name = "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun";
12 | obs_day_of_week = CFWS? day_name CFWS?;
13 | day_of_week = (FWS? day_name) | obs_day_of_week;
14 |
15 | # date
16 | obs_day = CFWS? (DIGIT | (DIGIT DIGIT)) CFWS?;
17 | day = (FWS? DIGIT DIGIT? FWS) | obs_day;
18 | month = "Jan" | "Feb" | "Mar" | "Apr" | "May" | "Jun" | "Jul" | "Aug" | "Sep" | "Oct" | "Nov" | "Dec";
19 | obs_year = CFWS? (DIGIT DIGIT DIGIT*) CFWS?;
20 | year = FWS DIGIT DIGIT DIGIT DIGIT FWS | obs_year;
21 | date = day month year;
22 |
23 | # time
24 | obs_hour = CFWS? (DIGIT DIGIT) CFWS?;
25 | hour = DIGIT DIGIT | obs_hour;
26 | obs_minute = CFWS? (DIGIT DIGIT) CFWS?;
27 | minute = DIGIT DIGIT | obs_minute;
28 | obs_second = CFWS? (DIGIT DIGIT) CFWS?;
29 | second = DIGIT DIGIT | obs_second;
30 | obs_zone = "UT" | "GMT" | "EST" | "EDT" | "CST" | "CDT" | "MST" | "MDT" | "PST" | "PDT" | 0x41..0x49 | 0x4B..0x5A | 0x61..0x69 | 0x6B..0x7A;
31 | time_of_day = hour ":" minute (":" second)?;
32 | zone = FWS ((("+" | "-") DIGIT DIGIT DIGIT DIGIT) | obs_zone);
33 | time = time_of_day zone;
34 |
35 | date_time = (day_of_week ",")?
36 | (date >date_s %date_e) <: (time >time_s %time_e) CFWS?;
37 | }%%
38 |
--------------------------------------------------------------------------------
/lib/mail/smtp_envelope.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Mail
4 | class SmtpEnvelope #:nodoc:
5 | # Reasonable cap on address length to avoid SMTP line length
6 | # overflow on old SMTP servers.
7 | MAX_ADDRESS_BYTESIZE = 2000
8 |
9 | attr_reader :from, :to, :message
10 |
11 | def initialize(mail)
12 | self.from = mail.smtp_envelope_from
13 | self.to = mail.smtp_envelope_to
14 | self.message = mail.encoded
15 | end
16 |
17 | def from=(addr)
18 | if Utilities.blank? addr
19 | raise ArgumentError, "SMTP From address may not be blank: #{addr.inspect}"
20 | end
21 |
22 | @from = validate_addr 'From', addr
23 | end
24 |
25 | def to=(addr)
26 | if Utilities.blank?(addr)
27 | raise ArgumentError, "SMTP To address may not be blank: #{addr.inspect}"
28 | end
29 |
30 | @to = Array(addr).map do |addr|
31 | validate_addr 'To', addr
32 | end
33 | end
34 |
35 | def message=(message)
36 | if Utilities.blank?(message)
37 | raise ArgumentError, 'SMTP message may not be blank'
38 | end
39 |
40 | @message = message
41 | end
42 |
43 |
44 | private
45 | def validate_addr(addr_name, addr)
46 | if addr.bytesize > MAX_ADDRESS_BYTESIZE
47 | raise ArgumentError, "SMTP #{addr_name} address may not exceed #{MAX_ADDRESS_BYTESIZE} bytes: #{addr.inspect}"
48 | end
49 |
50 | if /[\r\n]/.match?(addr)
51 | raise ArgumentError, "SMTP #{addr_name} address may not contain CR or LF line breaks: #{addr.inspect}"
52 | end
53 |
54 | addr
55 | end
56 | end
57 | end
58 |
--------------------------------------------------------------------------------
/lib/mail/values/unicode_tables.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikel/mail/d1d65b370b109b98e673a934e8b70a0c1f58cc59/lib/mail/values/unicode_tables.dat
--------------------------------------------------------------------------------
/lib/mail/version.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module Mail
3 | module VERSION
4 |
5 | MAJOR = 2
6 | MINOR = 9
7 | PATCH = 0
8 | BUILD = 'edge'
9 |
10 | STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
11 |
12 | def self.version
13 | STRING
14 | end
15 |
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/lib/mail/yaml.rb:
--------------------------------------------------------------------------------
1 | require 'yaml'
2 |
3 | module Mail
4 | module YAML
5 | def self.load(yaml)
6 | permitted_classes = [
7 | Symbol,
8 |
9 | Mail::Body,
10 |
11 | # Delivery methods as listed in mail/configuration.rb
12 | Mail::SMTP,
13 | Mail::Sendmail,
14 | Mail::Exim,
15 | Mail::FileDelivery,
16 | Mail::SMTPConnection,
17 | Mail::TestMailer,
18 | Mail::LoggerDelivery,
19 |
20 | Mail.delivery_method.class,
21 | ]
22 |
23 | if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0.pre1')
24 | ::YAML.safe_load(yaml, :permitted_classes => permitted_classes)
25 | else
26 | ::YAML.safe_load(yaml, permitted_classes)
27 | end
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/mail.gemspec:
--------------------------------------------------------------------------------
1 | require_relative 'lib/mail/version'
2 |
3 | Gem::Specification.new do |s|
4 | s.name = "mail"
5 | s.version = Mail::VERSION::STRING
6 | s.author = "Mikel Lindsaar"
7 | s.email = "raasdnil@gmail.com"
8 | s.homepage = "https://github.com/mikel/mail"
9 | s.description = "A really Ruby Mail handler."
10 | s.summary = "Mail provides a nice Ruby DSL for making, sending and reading emails."
11 | s.license = "MIT"
12 |
13 | s.extra_rdoc_files = %w[ README.md ]
14 | s.rdoc_options << '--exclude' << 'lib/mail/values/unicode_tables.dat'
15 |
16 | s.required_ruby_version = ">= 2.5"
17 |
18 | s.add_dependency('logger')
19 | s.add_dependency('mini_mime', '>= 0.1.1')
20 | s.add_dependency('net-smtp')
21 | s.add_dependency('net-imap')
22 | s.add_dependency('net-pop')
23 |
24 | s.add_development_dependency('bundler', '>= 1.0.3')
25 | s.add_development_dependency('rake', '> 0.8.7')
26 | s.add_development_dependency('rspec', '~> 3.0')
27 | s.add_development_dependency('rspec-benchmark')
28 | s.add_development_dependency('rdoc')
29 | s.add_development_dependency('rufo')
30 |
31 | s.files = Dir.glob(%w[ README.md MIT-LICENSE lib/**/* ])
32 | end
33 |
--------------------------------------------------------------------------------
/rakelib/ragel.rake:
--------------------------------------------------------------------------------
1 | # RFC 6532 extensions rely on RFC 3629 UTF-8 chars
2 | rule 'lib/mail/parsers/rfc5234_abnf_core_rules.rl' => 'lib/mail/parsers/rfc3629_utf8.rl'
3 |
4 | # All RFC 5322 parsers depend on ABNF core rules
5 | rule %r|rfc5322_.+\.rl\z| => 'lib/mail/parsers/rfc5234_abnf_core_rules.rl'
6 |
7 | # RFC 5322 parser depends on its submodules
8 | file 'lib/mail/parsers/rfc5322.rl' => FileList['lib/mail/parsers/rfc5322_*.rl']
9 |
10 | rule %r|_parser\.rl\z| => 'lib/mail/parsers/rfc5322.rl'
11 |
12 | # Ruby parsers depend on Ragel parser definitions
13 | # (remove -L to include line numbers for debugging)
14 | rule %r|_parser\.rb\z| => '%X.rl' do |t|
15 | sh "ragel -s -R -L -F1 -o #{t.name} #{t.source}"
16 | sh "bundle exec rufo --simple-exit #{t.name}"
17 | end
18 |
19 | # Dot files for Ragel parsers
20 | rule %r|_parser\.dot\z| => '%X.rl' do |t|
21 | sh "ragel -s -V -o #{t.name} #{t.source}"
22 | end
23 |
24 | rule %r|_parser\.svg\z| => '%X.dot' do |t|
25 | sh "dot -v -Tsvg -Goverlap=scale -o #{t.name} #{t.source}"
26 | end
27 |
28 | desc "Generate Ruby parsers from Ragel definitions"
29 | namespace :ragel do
30 | ragel_parsers = FileList['lib/mail/parsers/*_parser.rl']
31 | task :generate => ragel_parsers.ext('.rb')
32 | task :svg => ragel_parsers.ext('.svg')
33 | end
34 |
35 | task :ragel => 'ragel:generate'
36 |
--------------------------------------------------------------------------------
/spec/environment.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
3 |
4 | begin
5 | require 'byebug'
6 | rescue LoadError
7 | end
8 |
9 | require 'mail'
10 |
11 | if ENV['MBCHARS'] == 'activesupport'
12 | require 'active_support'
13 | Mail::Multibyte.proxy_class = ActiveSupport::Multibyte::Chars
14 | else
15 | require 'mail/multibyte/chars'
16 | Mail::Multibyte.proxy_class = Mail::Multibyte::Chars
17 | end
18 |
--------------------------------------------------------------------------------
/spec/fixtures/attachments/basic_email.eml:
--------------------------------------------------------------------------------
1 | Delivered-To: raasdnil@gmail.com
2 | Received: by 10.140.178.13 with SMTP id a13cs354079rvf;
3 | Fri, 21 Nov 2008 20:05:05 -0800 (PST)
4 | Received: by 10.151.44.15 with SMTP id w15mr2254748ybj.98.1227326704711;
5 | Fri, 21 Nov 2008 20:05:04 -0800 (PST)
6 | Return-Path: <test@lindsaar.net>
7 | Received: from mail11.tpgi.com.au (mail11.tpgi.com.au [203.12.160.161])
8 | by mx.google.com with ESMTP id 10si5117885gxk.81.2008.11.21.20.05.03;
9 | Fri, 21 Nov 2008 20:05:04 -0800 (PST)
10 | Received-SPF: neutral (google.com: 203.12.160.161 is neither permitted nor denied by domain of test@lindsaar.net) client-ip=203.12.160.161;
11 | Authentication-Results: mx.google.com; spf=neutral (google.com: 203.12.160.161 is neither permitted nor denied by domain of test@lindsaar.net) smtp.mail=test@lindsaar.net
12 | X-TPG-Junk-Status: Message not scanned
13 | X-TPG-Antivirus: Passed
14 | Received: from [192.0.0.253] (60-241-138-146.static.tpgi.com.au [60.0.0.146])
15 | by mail11.tpgi.com.au (envelope-from test@lindsaar.net) (8.14.3/8.14.3) with ESMTP id mAM44xew022221
16 | for <raasdnil@gmail.com>; Sat, 22 Nov 2008 15:05:01 +1100
17 | Message-Id: <6B7EC235-5B17-4CA8-B2B8-39290DEB43A3@test.lindsaar.net>
18 | From: Mikel Lindsaar <test@lindsaar.net>
19 | To: Mikel Lindsaar <raasdnil@gmail.com>
20 | Content-Type: text/plain; charset=US-ASCII; format=flowed
21 | Content-Transfer-Encoding: 7bit
22 | MIME-Version: 1.0 (Apple Message framework v929.2)
23 | Subject: Testing 123
24 | Date: Sat, 22 Nov 2008 15:04:59 +1100
25 | X-Mailer: Apple Mail (2.929.2)
26 |
27 | Plain email.
28 |
29 | Hope it works well!
30 |
31 | Mikel
32 |
--------------------------------------------------------------------------------
/spec/fixtures/attachments/test.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikel/mail/d1d65b370b109b98e673a934e8b70a0c1f58cc59/spec/fixtures/attachments/test.gif
--------------------------------------------------------------------------------
/spec/fixtures/attachments/test.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikel/mail/d1d65b370b109b98e673a934e8b70a0c1f58cc59/spec/fixtures/attachments/test.jpg
--------------------------------------------------------------------------------
/spec/fixtures/attachments/test.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikel/mail/d1d65b370b109b98e673a934e8b70a0c1f58cc59/spec/fixtures/attachments/test.pdf
--------------------------------------------------------------------------------
/spec/fixtures/attachments/test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikel/mail/d1d65b370b109b98e673a934e8b70a0c1f58cc59/spec/fixtures/attachments/test.png
--------------------------------------------------------------------------------
/spec/fixtures/attachments/test.tiff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikel/mail/d1d65b370b109b98e673a934e8b70a0c1f58cc59/spec/fixtures/attachments/test.tiff
--------------------------------------------------------------------------------
/spec/fixtures/attachments/test.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikel/mail/d1d65b370b109b98e673a934e8b70a0c1f58cc59/spec/fixtures/attachments/test.zip
--------------------------------------------------------------------------------
/spec/fixtures/attachments/てすと.txt:
--------------------------------------------------------------------------------
1 | this is a test
2 | これわてすと
--------------------------------------------------------------------------------
/spec/fixtures/emails/.gitattributes:
--------------------------------------------------------------------------------
1 | # Never autoconvert line endings on fixture emails
2 | *.eml -text
3 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/attachment_emails/attachment_content_disposition.eml:
--------------------------------------------------------------------------------
1 | MIME-Version: 1.0 (Apple Message framework v730)
2 | Content-Type: multipart/mixed; boundary=Apple-Mail-13-196941151
3 | Message-Id: <9169D984-4E0B-45EF-82D4-8F5E53AD7012@example.com>
4 | From: foo@example.com
5 | Subject: testing
6 | Date: Mon, 6 Jun 2005 22:21:22 +0200
7 | To: blah@example.com
8 |
9 |
10 | --Apple-Mail-13-196941151
11 | Content-Transfer-Encoding: quoted-printable
12 | Content-Type: text/plain;
13 | charset=ISO-8859-1;
14 | delsp=yes;
15 | format=flowed
16 |
17 | This is the first part.
18 |
19 | --Apple-Mail-13-196941151
20 | Content-Type: text/x-ruby-script; name="hello.rb"
21 | Content-Transfer-Encoding: 7bit
22 | Content-Disposition: attachment;
23 | filename="api.rb"
24 |
25 | puts "Hello, world!"
26 | gets
27 |
28 | --Apple-Mail-13-196941151--
29 |
30 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/attachment_emails/attachment_content_location.eml:
--------------------------------------------------------------------------------
1 | MIME-Version: 1.0 (Apple Message framework v730)
2 | Content-Type: multipart/mixed; boundary=Apple-Mail-13-196941151
3 | Message-Id: <9169D984-4E0B-45EF-82D4-8F5E53AD7012@example.com>
4 | From: foo@example.com
5 | Subject: testing
6 | Date: Mon, 6 Jun 2005 22:21:22 +0200
7 | To: blah@example.com
8 |
9 |
10 | --Apple-Mail-13-196941151
11 | Content-Transfer-Encoding: quoted-printable
12 | Content-Type: text/plain;
13 | charset=ISO-8859-1;
14 | delsp=yes;
15 | format=flowed
16 |
17 | This is the first part.
18 |
19 | --Apple-Mail-13-196941151
20 | Content-Type: image/jpeg
21 | Content-Transfer-Encoding: base64
22 | Content-Location: Photo25.jpg
23 | Content-ID: <qbFGyPQAS8>
24 | Content-Disposition: inline
25 |
26 | jamisSqGSIb3DQEHAqCAMIjamisxCzAJBgUrDgMCGgUAMIAGCSqGSjamisEHAQAAoIIFSjCCBUYw
27 | ggQujamisQICBD++ukQwDQYJKojamisNAQEFBQAwMTELMAkGA1UEBhMCRjamisAKBgNVBAoTA1RE
28 | QzEUMBIGjamisxMLVERDIE9DRVMgQ0jamisNMDQwMjI5MTE1OTAxWhcNMDYwMjamisIyOTAxWjCB
29 | gDELMAkGA1UEjamisEsxKTAnBgNVBAoTIEjamisuIG9yZ2FuaXNhdG9yaXNrIHRpbjamisRuaW5=
30 |
31 | --Apple-Mail-13-196941151--
32 |
33 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/attachment_emails/attachment_nonascii_filename.eml:
--------------------------------------------------------------------------------
1 | MIME-Version: 1.0 (Apple Message framework v730)
2 | Content-Type: multipart/mixed; boundary=Apple-Mail-13-196941151
3 | Message-Id: <9169D984-4E0B-45EF-82D4-8F5E53AD7012@example.com>
4 | From: foo@example.com
5 | Subject: testing
6 | Date: Mon, 6 Jun 2005 22:21:22 +0200
7 | To: blah@example.com
8 |
9 |
10 | --Apple-Mail-13-196941151
11 | Content-Transfer-Encoding: quoted-printable
12 | Content-Type: text/plain;
13 | charset=ISO-8859-1;
14 | delsp=yes;
15 | format=flowed
16 |
17 | This is the first part.
18 |
19 | --Apple-Mail-13-196941151
20 | Content-Type: text/plain; name=ciële.txt
21 | Content-Transfer-Encoding: 7bit
22 | Content-Disposition: attachment;
23 | filename=ciële.txt
24 |
25 | Hi there.
26 |
27 | --Apple-Mail-13-196941151--
28 |
29 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/attachment_emails/attachment_only_email.eml:
--------------------------------------------------------------------------------
1 | Subject: this message JUST contains an attachment
2 | From: Ryan Finnie <rfinnie@domain.dom>
3 | To: bob@domain.dom
4 | Content-Disposition: attachment; filename=blah.gz
5 | Content-Transfer-Encoding: base64
6 | Content-Description: Attachment has identical content to above foo.gz
7 | Message-Id: <1066974048.4264.62.camel@localhost>
8 | MIME-Version: 1.0
9 | Date: 23 Oct 2003 22:40:49 -0700
10 | Content-Type: application/x-gzip; NAME=blah.gz
11 |
12 | SubjectthismessageJUSTcontainsanattachmentFromRyanFinnierfinniedomaindomTobo
13 | bdomaindomContentDispositionattachmentfilenameAblahgzContentTypeapplication/
14 | xgzipnameAblahgzContentTransferEncodingbase64ContentDescriptionAttachmenthas
15 | identicalcontenttoabovefoogzMessageId1066974048426462camellocalhostMimeVersi
16 | on10Date23Oct20032240490700H4sIAOHBmD8AA4vML1XPyVHISy1LLVJIy8xLUchNVeQCAHbe7
17 | 64WA
--------------------------------------------------------------------------------
/spec/fixtures/emails/attachment_emails/attachment_with_base64_encoded_name.eml:
--------------------------------------------------------------------------------
1 | From xxxxxxxxx.xxxxxxx@gmail.com Sun May 8 19:07:09 2005
2 | Return-Path: <xxxxxxxxx.xxxxxxx@gmail.com>
3 | Message-ID: <e85734b90505081209eaaa17b@mail.gmail.com>
4 | Date: Sun, 8 May 2005 14:09:11 -0500
5 | From: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
6 | Reply-To: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
7 | To: xxxxx xxxx <xxxxx@xxxxxxxxx.com>
8 | Subject: Fwd: Signed email causes file attachments
9 | In-Reply-To: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
10 | MIME-Version: 1.0
11 | Content-Type: multipart/mixed;
12 | boundary="----=_Part_5028_7368284.1115579351471"
13 | References: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
14 |
15 | ------=_Part_5028_7368284.1115579351471
16 | Content-Type: text/plain; charset=ISO-8859-1
17 | Content-Transfer-Encoding: quoted-printable
18 | Content-Disposition: inline
19 |
20 | We should not include these files or vcards as attachments.
21 |
22 | ---------- Forwarded message ----------
23 | From: xxxxx xxxxxx <xxxxxxxx@xxx.com>
24 | Date: May 8, 2005 1:17 PM
25 | Subject: Signed email causes file attachments
26 | To: xxxxxxx@xxxxxxxxxx.com
27 |
28 |
29 | Hi,
30 |
31 | Test attachments with Base64 encoded filename.
32 |
33 |
34 | ------=_Part_5028_7368284.1115579351471
35 | Content-Type: application/pdf; name==?utf-8?B?VGhpcyBpcyBhIHRlc3QucGRm?=
36 | Content-Transfer-Encoding: base64
37 | Content-Disposition: attachment; filename==?utf-8?B?VGhpcyBpcyBhIHRlc3QucGRm?=
38 |
39 | MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIGFDCCAs0w
40 | ggI2oAMCAQICAw5c+TANBgkqhkiG9w0BAQQFADBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh
41 | d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVt
42 | YWlsIElzc3VpbmcgQ0EwHhcNMDUwMzI5MDkzOTEwWhcNMDYwMzI5MDkzOTEwWjBCMR8wHQYDVQQD
43 | ExZUaGF3dGUgRnJlZW1haWwgTWVtYmVyMR8wHQYJKoZIhvcNAQkBFhBzbWhhdW5jaEBtYWMuY29t
44 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn90dPsYS3LjfMY211OSYrDQLzwNYPlAL
45 | 7+/0XA+kdy8/rRnyEHFGwhNCDmg0B6pxC7z3xxJD/8GfCd+IYUUNUQV5m9MkxfP9pTVXZVIYLaBw
46 | ------=_Part_5028_7368284.1115579351471--
47 |
48 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/attachment_emails/attachment_with_encoded_name.eml:
--------------------------------------------------------------------------------
1 | From xxxxxxxxx.xxxxxxx@gmail.com Sun May 8 19:07:09 2005
2 | Return-Path: <xxxxxxxxx.xxxxxxx@gmail.com>
3 | Message-ID: <e85734b90505081209eaaa17b@mail.gmail.com>
4 | Date: Sun, 8 May 2005 14:09:11 -0500
5 | From: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
6 | Reply-To: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
7 | To: xxxxx xxxx <xxxxx@xxxxxxxxx.com>
8 | Subject: Fwd: Signed email causes file attachments
9 | In-Reply-To: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
10 | MIME-Version: 1.0
11 | Content-Type: multipart/mixed;
12 | boundary="----=_Part_5028_7368284.1115579351471"
13 | References: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
14 |
15 | ------=_Part_5028_7368284.1115579351471
16 | Content-Type: text/plain; charset=ISO-8859-1
17 | Content-Transfer-Encoding: quoted-printable
18 | Content-Disposition: inline
19 |
20 | We should not include these files or vcards as attachments.
21 |
22 | ---------- Forwarded message ----------
23 | From: xxxxx xxxxxx <xxxxxxxx@xxx.com>
24 | Date: May 8, 2005 1:17 PM
25 | Subject: Signed email causes file attachments
26 | To: xxxxxxx@xxxxxxxxxx.com
27 |
28 |
29 | Hi,
30 |
31 | Test attachments oddly encoded with japanese charset.
32 |
33 |
34 | ------=_Part_5028_7368284.1115579351471
35 | Content-Type: application/octet-stream; name*=iso-2022-jp'ja'01%20Quien%20Te%20Dij%8aat.%20Pitbull.mp3
36 | Content-Transfer-Encoding: base64
37 | Content-Disposition: attachment
38 |
39 | MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIGFDCCAs0w
40 | ggI2oAMCAQICAw5c+TANBgkqhkiG9w0BAQQFADBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh
41 | d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVt
42 | YWlsIElzc3VpbmcgQ0EwHhcNMDUwMzI5MDkzOTEwWhcNMDYwMzI5MDkzOTEwWjBCMR8wHQYDVQQD
43 | ExZUaGF3dGUgRnJlZW1haWwgTWVtYmVyMR8wHQYJKoZIhvcNAQkBFhBzbWhhdW5jaEBtYWMuY29t
44 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn90dPsYS3LjfMY211OSYrDQLzwNYPlAL
45 | 7+/0XA+kdy8/rRnyEHFGwhNCDmg0B6pxC7z3xxJD/8GfCd+IYUUNUQV5m9MkxfP9pTVXZVIYLaBw
46 | ------=_Part_5028_7368284.1115579351471--
47 |
48 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/attachment_emails/attachment_with_unquoted_name.eml:
--------------------------------------------------------------------------------
1 | MIME-Version: 1.0 (Apple Message framework v730)
2 | Content-Type: multipart/mixed; boundary=Apple-Mail-13-196941151
3 | Message-Id: <9169D984-4E0B-45EF-82D4-8F5E53AD7012@example.com>
4 | From: foo@example.com
5 | Subject: testing
6 | Date: Mon, 6 Jun 2005 22:21:22 +0200
7 | To: blah@example.com
8 |
9 |
10 | --Apple-Mail-13-196941151
11 | Content-Transfer-Encoding: quoted-printable
12 | Content-Type: text/plain;
13 | charset=ISO-8859-1;
14 | delsp=yes;
15 | format=flowed
16 |
17 | This is the first part.
18 |
19 | --Apple-Mail-13-196941151
20 | Content-Type: text/plain; name=This is a test.txt
21 | Content-Transfer-Encoding: 7bit
22 | Content-Disposition: attachment;
23 | filename=This is a test.txt
24 |
25 | Hi there.
26 |
27 | --Apple-Mail-13-196941151--
28 |
29 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/bad_date_header2.eml:
--------------------------------------------------------------------------------
1 | X-Message-Delivery: Vj0xLjE7dXM9MDtsPTA7YT0xO0Q9MTtTQ0w9MA==
2 | X-Message-Status: n
3 | X-SID-PRA: enews@Free-Quilting.com
4 | X-AUTH-Result: NONE
5 | X-Message-Info: JGTYoYF78jHCcITVD+zs6u3ahcolNfp0m61kNO2SBMwKZtwdSoGZLR+eV3xtqv3QU2mvP3b1AtESP6eCYbaI4dABkTSkMMCjZGPGH3Q01dsRSddQ0kCWDw==
6 | Received: from drg.drgnetwork.com ([63.76.155.39]) by col0-mc2-f14.Col0.hotmail.com with Microsoft SMTPSVC(6.0.3790.4675);
7 | Tue, 14 Dec 2010 22:59:10 -0800
8 | Received: from SFGAS1.DRGNETWORK.COM (sfgas1.drgnetwork.com [63.76.155.11])
9 | by drg.drgnetwork.com (8.13.8/8.13.8) with ESMTP id oBF6xAuc018214
10 | for <someone@live.com>; Wed, 15 Dec 2010 00:59:10 -0600
11 | Message-Id: <201012150659.oBF6xAuc018214@drg.drgnetwork.com>
12 | Sender: enews@Free-Quilting.com
13 | Date: Wed, 15 Dec 2010 59:10 -0500
14 | From: "Free-Quilting.com" <enews@Free-Quilting.com>
15 | MIME-Version: 1.0
16 | To: <someone@live.com>
17 | cc:
18 | Subject: 40% OFF holiday patterns and fabric!
19 | Content-Type: multipart/alternative; boundary="--PART.BOUNDARY.0001"
20 | Return-Path: bounces@strategicfulfillment.com
21 | X-OriginalArrivalTime: 15 Dec 2010 06:59:10.0647 (UTC) FILETIME=[93232C70:01CB9C25]
22 |
23 |
24 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/bad_encoded_subject.eml:
--------------------------------------------------------------------------------
1 | Subject: =?NONE?B?VEVTVA=?=
2 |
3 | TEST
4 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/cant_parse_from.eml:
--------------------------------------------------------------------------------
1 | Date: Thu, 11 Jun 2009 23:25:02 -0700
2 | From: Apple <News@InsideApple.Apple.com>
3 | To: karl.baum@gmail.com
4 | Message-Id: <7oh6b1$1clhrjk@badger-vip.apple.com>
5 | Subject: Meet the new MacBook Pro family. Now includes 13-inch.
6 | MIME-Version: 1.0
7 | Content-Type: multipart/alternative; boundary=mimepart_4b0c353551675_3d1c15b79ea5e70c1783
8 |
9 |
10 | --mimepart_4b0c353551675_3d1c15b79ea5e70c1783
11 | Content-Type: text/plain; charset=ISO-8859-1
12 | Content-Transfer-Encoding: Quoted-printable
13 | Content-Disposition: inline
14 |
15 | From one solid piece of aluminum comes a MacBook Pro that's thin and light,=
16 | beautifully streamlined, and durable.
17 |
18 | --mimepart_4b0c353551675_3d1c15b79ea5e70c1783
19 | Content-Type: text/html; charset=ISO-8859-1
20 | Content-Transfer-Encoding: Quoted-printable
21 | Content-Disposition: inline
22 |
23 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
24 | <html>
25 | <head>
26 | <body>
27 | From one solid piece of aluminum comes a MacBook Pro that's thin and light,=
28 | beautifully streamlined, and durable.<br><a href=3D"http://insideapple.app=
29 | </body>
30 | </html>
31 |
32 | --mimepart_4b0c353551675_3d1c15b79ea5e70c1783--
33 |
34 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/content_transfer_encoding_qp_with_space.eml:
--------------------------------------------------------------------------------
1 | Return-Path: <fyouizjnp@swissonline.ch>
2 | Delivered-To: em-ca-bait-precedes@em.ca
3 | Received: (qmail 7622 invoked by uid 115); 7 Nov 2004 21:30:59 -0000
4 | Received: from fyouizjnp@swissonline.ch by churchill by uid 64011 with qmail-scanner-1.22
5 | (clamdscan: 0.75-1. spamassassin: 2.63. Clear:RC:0(222.47.112.31):.
6 | Processed in 1.163709 secs); 07 Nov 2004 21:30:59 -0000
7 | Received: from unknown (HELO 209.5.178.248) (222.47.112.31)
8 | by churchill.factcomp.com with SMTP; 7 Nov 2004 21:30:57 -0000
9 | Message-ID: <qlrqpxforpx$RND_WORDjyeottngpx@sympatico.ca>
10 | From: "Wilmer Capps" <fyouizjnp@swissonline.ch>
11 | To: bait-passover@em.ca
12 | Subject: Low or High Blood Pressure? We can help.
13 | Date: Sun, 07 Nov 2004 18:23:56 -0300
14 | X-Mailer: gene annulus
15 | pneumococcus-polyhedral: belgrade hanoverian lima
16 | MIME-Version: 1.0
17 | Content-Type: multipart/alternative;
18 | boundary="----=_NextPart_000_003A_5008K66J.3Z4LC80J"
19 |
20 | This is a multi-part message in MIME format.
21 |
22 | ------=_NextPart_000_003A_5008K66J.3Z4LC80J
23 | Content-Type: text/plain;
24 | charset="iso-8859-1"
25 | Content-Transfer-Encoding: quoted printable
26 |
27 | If you're in need of a good RX site for online purchases, we are your answer.
28 |
29 | With Tens of Thousands of happy customers who saved huge, you can't go wrong.
30 |
31 | http://magyar8stator.com/26 Lots More Info Here
32 |
33 | Above URL is for more info & if you are interested.
34 | ------=_NextPart_000_003A_5008K66J.3Z4LC80J
35 | Content-Type: text/html;
36 | charset="iso-8859-1"
37 | Content-Transfer-Encoding: quoted-printable
38 |
39 | If you're in need of a good RX site for online purchases, we are your answ=
40 | er.<br>
41 | <br>
42 | With Tens of Thousands of happy customers who saved huge, you can't go wro=
43 | ng.<br>
44 | <br>
45 | <a href=3D"http://magyar8stator.com/26">Lots More Info Here</a><br>
46 | <br>
47 | <br>
48 | Above URL is for more info & if you are interested.<br>
49 |
50 |
51 |
52 |
53 | ------=_NextPart_000_003A_5008K66J.3Z4LC80J--
54 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/content_transfer_encoding_text-html.eml:
--------------------------------------------------------------------------------
1 | Return-Path: <hzwfrkq@hintontile.com>
2 | Delivered-To: rait@bruce-guenter.dyndns.org
3 | Received: (qmail 12977 invoked from network); 6 May 2005 10:58:40 -0000
4 | Received: from localhost (localhost [127.0.0.1])
5 | by bruce-guenter.dyndns.org ([192.168.1.3]); 06 May 2005 10:58:40 -0000
6 | Received: from zak.futurequest.net ([127.0.0.1])
7 | by localhost ([127.0.0.1])
8 | with SMTP via TCP; 06 May 2005 10:58:40 -0000
9 | Received: (qmail 2252 invoked from network); 6 May 2005 10:58:39 -0000
10 | Received: from lsne-catv-dhcp-29-115.urbanet.ch (unknown [80.238.29.115])
11 | by zak.futurequest.net ([69.5.6.152])
12 | with SMTP via TCP; 06 May 2005 10:58:29 -0000
13 | Received: from mail.datavalet.com (80.238.29.115)
14 | by 80.238.29.115 (fairwayv.4) with SMTP
15 | id <09166i58p>
16 | (Authid: 3811297); Fri, 06 May 2005 10:52:01 -0100
17 | Reply-To: "chianfong cuthbert" <abhijit.862153drinnan@datavalet.com>
18 | From: "chianfong cuthbert" <abhijit.862153drinnan@datavalet.com>
19 | To: cvs@bruce-guenter.dyndns.org
20 | Cc: rait@bruce-guenter.dyndns.org
21 | Subject: Re: We will help you refinance your home.
22 | Date: Fri, 06 May 2005 15:55:01 +0400
23 | MIME-Version: 1.0
24 | Content-Type: multipart/alternative;
25 | boundary="--651790_269334.01570"
26 | Content-Length: 636
27 | Lines: 22
28 |
29 | ----651790_269334.01570
30 | Content-Type: text/html;
31 | charset="iso-8859-1"
32 | Content-Transfer-Encoding: text/html
33 |
34 | Hello,<p>
35 |
36 | You have qualified for the lowest rate in years.<br>
37 | You could get over $400,000 for as little as $500 a month.<br>
38 | Low rates are fixed no matter what.<p>
39 |
40 | Please visit the link below to verify your information:<br>
41 | <a href="http://www.lenxzc.com/index2.php?refid=malx">Approval Form</a><p>
42 |
43 | Best Regards,<br>
44 | chianfong cuthbert, Account Manager<br>
45 | Reynolds Associates, LLC<p>
46 | <p>
47 | --------------------<br>
48 | if you received this in error: <a href="http://www.lenxzc.com/r.php">re-m0-ve</a>
49 |
50 | ----651790_269334.01570--
51 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/encoding_madness.eml:
--------------------------------------------------------------------------------
1 | Delivered-To: e-f5f4@app.ar-example.com
2 | Received: by 10.2.1.1 with SMTP id p21cs62610wem;
3 | Wed, 22 Sep 2010 00:30:55 -0700 (PDT)
4 | Received: by 10.15.2.1 with SMTP id p24mr499372ybh.380.1285140655013;
5 | Wed, 22 Sep 2010 00:30:55 -0700 (PDT)
6 | Return-Path: <production@aquila.el-example.org>
7 | Received: from aquila.el-example.org ([174.1.8.2])
8 | by mx.google.com with ESMTP id a6si11272839ybo.18.2010.09.22.00.30.54;
9 | Wed, 22 Sep 2010 00:30:54 -0700 (PDT)
10 | Received-SPF: neutral (google.com: 174.1.8.2 is neither permitted nor denied by best guess record for domain of production@aquila.el-example.org) client-ip=174.1.8.2;
11 | Authentication-Results: mx.google.com; spf=neutral (google.com: 174.1.8.2 is neither permitted nor denied by best guess record for domain of production@aquila.el-example.org) smtp.mail=production@aquila.el-example.org
12 | Received: from aquila.el-example.org (localhost [127.0.0.1])
13 | by aquila.el-example.org (8.14.2/8.14.2) with ESMTP id o8M7UrfD018673
14 | for <e-f5f4@app.ar-example.com>; Wed, 22 Sep 2010 02:30:54 -0500 (CDT)
15 | (envelope-from production@aquila.el-example.org)
16 | Received: (from production@localhost)
17 | by aquila.el-example.org (8.14.2/8.14.2/Submit) id o8M7Urh3018672;
18 | Wed, 22 Sep 2010 02:30:53 -0500 (CDT)
19 | (envelope-from production)
20 | Message-Id: <201009220730.o8M7Urh3018672@aquila.el-example.org>
21 | MIME-Version: 1.0
22 | Content-Disposition: inline
23 | Content-Transfer-Encoding: quoted-printable
24 | Content-Type: text/plain
25 | X-Mailer: MIME::Lite 3.027 (F2.74; T1.28; A2.04; B3.07; Q3.07)
26 | Date: Wed, 22 Sep 2010 02:30:53 -0500
27 | From: no-reply@crm.el-example.org
28 | To: e-f5f4@app.ar-example.com
29 | Reply-To: "KLAUS- HÄNSCHEL" <>
30 | Subject: eBay Bid - 2008 Ford Super Duty F-350 DRW King Ranch Crew Cab 4x4 (156) - Stock# XXXX
31 |
32 | Body Text
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/header_fields_with_empty_values.eml:
--------------------------------------------------------------------------------
1 | Received: from mx01.medieveven.no (192.168.42.42) by epost.vartland.no
2 | (192.168.73.7) with Microsoft SMTP Server id 8.1.393.1; Fri, 30 Oct 2009
3 | 20:08:07 +0100
4 | Received: from woodward.joyent.us ([8.12.42.230]) by mx01.medieveven.no with
5 | ESMTP; 30 Oct 2009 20:11:23 +0100
6 | Received: from [10.0.0.5] (ti0083a340-0282.bb.online.no [88.89.59.28]) by
7 | woodward.joyent.us (Postfix) with ESMTPSA id EC35240C85 for
8 | <aftest@adfontesmedier.no>; Fri, 30 Oct 2009 19:07:44 +0000 (GMT)
9 | From: =?iso-8859-1?Q?J=F8rn_St=F8ylen?= <jorn@prikkprikkprikk.no>
10 | To: AF Test <aftest@adfontesmedier.no>
11 | Date: Fri, 30 Oct 2009 20:07:42 +0100
12 | Subject: Testmail
13 | Thread-Topic: Testmail
14 | Thread-Index: AcpZlFLF/Y9EfcC0QZKKEuUFm2Snqw==
15 | Message-ID: <4FDC124A-1FC4-4B29-8502-E459BD9AB397@prikkprikkprikk.no>
16 | Accept-Language: nb-NO
17 | X-MS-Exchange-Organization-AuthAs: Anonymous
18 | X-MS-Exchange-Organization-AuthSource: epost.vartland.no
19 | X-MS-Has-Attach:
20 | X-MS-TNEF-Correlator:
21 | x-ironport-anti-spam-filtered: true
22 | x-ironport-av: E=Sophos;i="4.44,655,1249250400"; d="scan'208";a="2439461"
23 | x-ironport-anti-spam-result: AvMBAPfV6koIDCrmhWdsb2JhbACbVgEBAQoLChoDxH2EPQQ
24 | Content-Type: text/plain; charset="iso-8859-1"
25 | Content-Transfer-Encoding: quoted-printable
26 | MIME-Version: 1.0
27 |
28 |
29 |
30 | --
31 | J=F8rn St=F8ylen -- http://www.prikkprikkprikk.no
32 | 924 38 051 -- jorn@prikkprikkprikk.no
33 |
34 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/invalid_subject_characters.eml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikel/mail/d1d65b370b109b98e673a934e8b70a0c1f58cc59/spec/fixtures/emails/error_emails/invalid_subject_characters.eml
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/missing_body.eml:
--------------------------------------------------------------------------------
1 | Message-ID: <001301c17797$9cd0ef30$a3ab620c@vaio>
2 | From: "SCS_2" <redacted@attglobal.net>
3 | To: <Undisclosed-Recipient:@mailman.enron.com;>
4 | Subject: REDACTED
5 | Date: Tue, 27 Nov 2001 15:02:35 -0800
6 | MIME-Version: 1.0
7 | Content-Type: multipart/mixed;
8 | boundary="----=_NextPart_000_000F_01C17754.8C3CAF30"
9 | X-Priority: 3
10 | X-MSMail-Priority: Normal
11 | X-Mailer: Microsoft Outlook Express 5.00.2919.6700
12 | X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2919.6700
13 | Return-Path: redacted@attglobal.net
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/multiple_content_types.eml:
--------------------------------------------------------------------------------
1 | From: <redacted@flashmail.net>
2 | Subject: Redacted
3 | To: <redacted@Enron.com>
4 | Message-ID: <105647271315.NCV17523@x263.net>
5 | MIME-version: 1.0
6 | Content-Type: multipart/alternative; boundary="----_001_5973_47T00ZN9.15SY2428"
7 | Content-type: text/plain
8 |
9 | This is a multi-part message in MIME format.
10 |
11 | ------_001_5973_47T00ZN9.15SY2428
12 | Content-Type: text/plain;
13 | charset="utf-8"
14 | Content-Transfer-Encoding: 7Bit
15 |
16 | foo
17 |
18 | ------_001_5973_47T00ZN9.15SY2428
19 | Content-Type: text/html;
20 | charset="utf-8"
21 | Content-Transfer-Encoding: 7Bit
22 |
23 | <p>foo</p>
24 |
25 | ------_001_5973_47T00ZN9.15SY2428--
26 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/multiple_invalid_content_dispositions.eml:
--------------------------------------------------------------------------------
1 | From: <redacted@flashmail.net>
2 | Subject: Redacted
3 | To: <redacted@Enron.com>
4 | Message-ID: <105647271315.NCV17523@x263.net>
5 | MIME-version: 1.0
6 | Content-Type: text/html;
7 | charset=utf-8
8 | Content-Disposition: =?utf-8?Q?invalid?=
9 | Content-Transfer-Encoding: quoted-printable
10 | Content-Disposition: =?utf-8?Q?invalid?=
11 |
12 | <p>foo</p>
13 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/multiple_references_with_one_invalid.eml:
--------------------------------------------------------------------------------
1 | From: <redacted@flashmail.net>
2 | Subject: Redacted
3 | To: <redacted@Enron.com>
4 | Message-ID: <105647271315.NCV17523@x263.net>
5 | MIME-version: 1.0
6 | Content-Type: multipart/alternative; boundary="----_001_5973_47T00ZN9.15SY2428"
7 | References: <foo@bar.net>
8 | References: <baz@bar.net>, <invalid.
9 | something@bar.net>
10 |
11 | This is a multi-part message in MIME format.
12 |
13 | ------_001_5973_47T00ZN9.15SY2428
14 | Content-Type: text/plain;
15 | charset="utf-8"
16 | Content-Transfer-Encoding: 7Bit
17 |
18 | foo
19 |
20 | ------_001_5973_47T00ZN9.15SY2428
21 | Content-Type: text/html;
22 | charset="utf-8"
23 | Content-Transfer-Encoding: 7Bit
24 |
25 | <p>foo</p>
26 |
27 | ------_001_5973_47T00ZN9.15SY2428--
28 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/must_supply_encoding.eml:
--------------------------------------------------------------------------------
1 | X-YMAIL-UMID: 1_132725_AEe3iGIAAGS4TOAfWQ3foSiBC54
2 | X-Apparently-To: anyone@yahoo.com via 98.136.183.71; Sun, 14 Nov 2010 09:41:45 -0800
3 | Message-Id: <201011141741.oAEHfiKs020181@app9.msg2u.net>
4 | MIME-Version: 1.0
5 | Content-Transfer-Encoding: binary
6 | Content-Type: multipart/alternative; boundary="_----------=_128975650412616235"
7 | X-Mailer: MIME::Lite 3.020 (F2.73; T1.21; A1.77; B3.01; Q3.01)
8 | Date: Sun, 14 Nov 2010 17:41:44 +0000
9 | From: Biz Phone Systems from EclipseMediaOnline�� <info@here2there-travelers-msgs.net>
10 | To: anyone@YAHOO.COM
11 | Subject: Impress your clients with a business phone���
12 | Reply-To: Biz Phone Systems from EclipseMediaOnline�� <44.41.17.14.11.2010.1139.1.328.1477949.614@reply.here2there-travelers-msgs.net>
13 |
14 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/new_line_in_to_header.eml:
--------------------------------------------------------------------------------
1 | Delivered-To: e-s-a-g-8718@app.ar.com
2 | Received: by 10.2.1.1 with SMTP id c60cs12954wel;
3 | Wed, 13 Oct 2010 07:44:39 -0700 (PDT)
4 | Received: by 10.15.1.1 with SMTP id f12mr1139775ybe.360.1286981078364;
5 | Wed, 13 Oct 2010 07:44:38 -0700 (PDT)
6 | Return-Path: <l@gcn-example.com>
7 | Received: from services.travidiabamboo.com (services.travidiabamboo.com [72.21.1.1])
8 | by mx.google.com with ESMTP id v33si16714378yba.88.2010.10.13.07.44.37;
9 | Wed, 13 Oct 2010 07:44:38 -0700 (PDT)
10 | Received-SPF: pass (google.com: domain of l@gcn-example.com designates 72.21.1.1 as permitted sender) client-ip=72.21.1.1;
11 | Authentication-Results: mx.google.com; spf=pass (google.com: domain of l@gcn-example.com designates 72.21.1.1 as permitted sender) smtp.mail=l@gcn-example.com
12 | Received: from travidiabamboo.com (services [10.0.0.2])
13 | by services.travidiabamboo.com (Postfix) with ESMTP id A532170702;
14 | Wed, 13 Oct 2010 07:53:04 -0700 (PDT)
15 | Date: Wed, 13 Oct 2010 07:53:04 -0700
16 | From: l@gcn-example.com
17 | To: leads@sg.dc.com,
18 | sag@leads.gs.ry.com,
19 | sn@example-hotmail.com,
20 | e-s-a-g-8718@app.ar.com,
21 | jp@t-exmaple.com,
22 |
23 | cc@c-l-example.com
24 | Message-Id: <4cb5c7d0a3cce_120e..fdbed2b861958562@s.t-example.com.tmail>
25 | Subject: [Online Lead] Online Lead #1111111
26 | MIME-Version: 1.0
27 | Content-Type: text/plain; charset=utf-8
28 |
29 | <?xml version="1.0" encoding="UTF-8"?>
30 | <?ADF version="1.0"?><adf>
31 | <prospect>
32 | <requestdate>2010-10-13T07:53:04-09:00</requestdate>
33 | ... (not important) ...
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/trademark_character_in_subject.eml:
--------------------------------------------------------------------------------
1 | Delivered-To: e-r-w-a-4462@app.ar.com
2 | Received: by 10.1.1.1 with SMTP id w10cs10896muo;
3 | Tue, 12 Oct 2010 13:20:24 -0700 (PDT)
4 | Received: by 10.2.1.5 with SMTP id bk15mr6105827qab.89.1286914824124;
5 | Tue, 12 Oct 2010 13:20:24 -0700 (PDT)
6 | Return-Path: <j@yahoo-example.com>
7 | Received: from mail.ga-example.com (mail.ga-example.com [64.1.2.3])
8 | by mx.google.com with ESMTP id 13si112341247qcd.23.2010.10.12.13.20.23;
9 | Tue, 12 Oct 2010 13:20:24 -0700 (PDT)
10 | Received-SPF: neutral (google.com: 64.1.2.3 is neither permitted nor denied by best guess record for domain of j@yahoo-example.com) client-ip=64.1.2.3;
11 | Authentication-Results: mx.google.com; spf=neutral (google.com: 64.1.2.3 is neither permitted nor denied by best guess record for domain of j@yahoo-example.com) smtp.mail=j@yahoo-example.com
12 | X-MDAV-Processed: mail.ga-example.com, Tue, 12 Oct 2010 16:21:07 -0400
13 | X-Spam-Processed: mail.ga-example.com, Tue, 12 Oct 2010 16:21:06 -0400
14 | X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on
15 | MAIL02.VD-example.com
16 | X-Spam-Level:
17 | X-Spam-Status: No, score=-1.1 required=5.0 tests=BAYES_00,DATE_IN_PAST_03_06,
18 | FORGED_YAHOO_RCVD,INVALID_DATE,NO_RELAYS,SUBJECT_NEEDS_ENCODING
19 | shortcircuit=no autolearn=no version=3.2.5
20 | Received: from GAWWW03 by ga-example.com (MDaemon PRO v11.0.3)
21 | with ESMTP id md50004804310.msg
22 | for <e-r-w-a-4462@app.ar.com>; Tue, 12 Oct 2010 16:21:05 -0400
23 | X-MDRemoteIP: 192.168.254.73
24 | X-Return-Path: j@yahoo-example.com
25 | X-Envelope-From: j@yahoo-example.com
26 | X-MDaemon-Deliver-To: e-r-w-a-4462@app.ar.com
27 | Date: Tue, 12 Oct 2010 16:21:05 H0500
28 | Subject: GA.comô has a lead for you
29 | To: c@ra-example.com,e-r-w-a-4462@app.ar.com,leads@ga-example.com
30 | MIME-Version: 1.0
31 | Content-type: text/plain; charset=iso-8859-1
32 | From: j@yahoo-example.com
33 | Message-ID: <MDAEMON-F201010121621.AA2105420md50000198258@ga-example.com>
34 |
35 | Body Text - not important
--------------------------------------------------------------------------------
/spec/fixtures/emails/error_emails/weird_to_header.eml:
--------------------------------------------------------------------------------
1 | Delivered-To: e-s-a-s-2200@app.ar.com
2 | Received: by 10.103.1.1 with SMTP id w10cs50835muo;
3 | Thu, 14 Oct 2010 20:25:16 -0700 (PDT)
4 | Received: by 10.150.205.4 with SMTP id c4mr736200ybg.26.1287113115711;
5 | Thu, 14 Oct 2010 20:25:15 -0700 (PDT)
6 | Return-Path: <anonymous@i.tp.host>
7 | Received: from i.tp.host ([172.1.1.1])
8 | by mx.google.com with ESMTP id s21si2123456.90.2010.10.14.20.25.15;
9 | Thu, 14 Oct 2010 20:25:15 -0700 (PDT)
10 | Received-SPF: neutral (google.com: 172.1.1.1 is neither permitted nor denied by best guess record for domain of anonymous@i.tp.host) client-ip=172.1.1.1;
11 | Authentication-Results: mx.google.com; spf=neutral (google.com: 172.1.1.1 is neither permitted nor denied by best guess record for domain of anonymous@i.tp.host) smtp.mail=anonymous@i.tp.host
12 | Received: (qmail 28454 invoked by uid 48); 14 Oct 2010 23:25:06 -0400
13 | Date: 14 Oct 2010 23:25:06 -0400
14 | Message-ID: <20101015032506.28448.qmail@i.tp.host>
15 | From: anonymous@i.tp.host
16 | To: , user-example@aol.com, e-s-a-s-2200@app.ar.com
17 | Subject:
18 |
19 |
20 | CONTACT:
21 |
22 |
23 |
24 |
25 | COMMENT:
26 |
27 |
28 | PAGE THEY WERE ON:
29 |
30 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/mime_emails/email_with_similar_boundaries.eml:
--------------------------------------------------------------------------------
1 | Received: from xxxx.xxxxxxx.xxx (127.0.0.1) by
2 | xxxx.xxxxxxxx.xxx (127.0.01) with Microsoft SMTP Server id
3 | 11.1.111.1; Thu, 5 Apr 2012 01:01:01 -0700
4 | Message-ID: <e4b473$b3jkq@xxxx.xxxx.xxxxxxxx.xxx>
5 | To: <xxxxxxx@xxxxxxxxxxx.xxx>
6 | Subject: Xxxxxx
7 | Date: Fri, 6 Apr 2012 01:01:01 +0000
8 | From: Xxxxx <xxxxxx@xxxxxxxx.xxx>
9 | X-Mailer: PHP/5.2.6
10 | Content-Type: multipart/mixed;
11 | boundary="----=_NextPart_476c4fde88e507bb8028170e8cf47c73"
12 | MIME-Version: 1.0
13 |
14 | ------=_NextPart_476c4fde88e507bb8028170e8cf47c73
15 | Content-Type: multipart/alternative;
16 | boundary="----=_NextPart_476c4fde88e507bb8028170e8cf47c73_alt"
17 |
18 | ------=_NextPart_476c4fde88e507bb8028170e8cf47c73_alt
19 | Content-Type: text/plain; charset="utf-8"
20 | Content-Transfer-Encoding: 8bit
21 |
22 | Test
23 |
24 | ------=_NextPart_476c4fde88e507bb8028170e8cf47c73_alt
25 | Content-Type: text/html; charset="utf-8"
26 | Content-Transfer-Encoding: 8bit
27 |
28 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd"><html><head>
29 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
30 | <title>Test</title>
31 | <body>
32 | <p>Test</p>
33 | </body>
34 |
35 | ------=_NextPart_476c4fde88e507bb8028170e8cf47c73_alt--
36 |
37 | ------=_NextPart_476c4fde88e507bb8028170e8cf47c73
38 | Content-Type: application/octetstream
39 | Content-Transfer-Encoding: base64
40 | Content-Disposition: attachment; filename="LOGO.png"
41 | Content-ID: <LOGO.png>
42 |
43 | SNIP
44 |
45 | ------=_NextPart_476c4fde88e507bb8028170e8cf47c73--
46 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/mime_emails/raw_email11.eml:
--------------------------------------------------------------------------------
1 | From xxx@xxxx.com Wed Apr 27 14:15:31 2005
2 | MIME-Version: 1.0 (Apple Message framework v619.2)
3 | To: "xxxxx@xxxxx" <matmail>
4 | Message-Id: <416eaebec6d333ec6939eaf8a7d80724@xxxxx>
5 | Content-Type: multipart/alternative;
6 | boundary=Apple-Mail-5-1037861608
7 | From: "xxxxx@xxxxx" <xxxxx@xxxxx>
8 | Subject: worse when you use them.
9 | Date: Wed, 27 Apr 2005 14:15:31 -0700
10 |
11 |
12 |
13 |
14 | --Apple-Mail-5-1037861608
15 | Content-Transfer-Encoding: 7bit
16 | Content-Type: text/plain;
17 | charset=US-ASCII;
18 | format=flowed
19 |
20 |
21 | XXXXX Xxxxx
22 |
23 | --Apple-Mail-5-1037861608
24 | Content-Transfer-Encoding: 7bit
25 | Content-Type: text/enriched;
26 | charset=US-ASCII
27 |
28 |
29 |
30 | <bold>XXXXX Xxxxx</bold>
31 |
32 |
33 | --Apple-Mail-5-1037861608--
34 |
35 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/mime_emails/raw_email12.eml:
--------------------------------------------------------------------------------
1 | MIME-Version: 1.0 (Apple Message framework v730)
2 | Content-Type: multipart/mixed; boundary=Apple-Mail-13-196941151
3 | Message-Id: <9169D984-4E0B-45EF-82D4-8F5E53AD7012@example.com>
4 | From: foo@example.com
5 | Subject: testing
6 | Date: Mon, 6 Jun 2005 22:21:22 +0200
7 | To: blah@example.com
8 |
9 |
10 | --Apple-Mail-13-196941151
11 | Content-Transfer-Encoding: quoted-printable
12 | Content-Type: text/plain;
13 | charset=ISO-8859-1;
14 | delsp=yes;
15 | format=flowed
16 |
17 | This is the first part.
18 |
19 | --Apple-Mail-13-196941151
20 | Content-Type: image/jpeg
21 | Content-Transfer-Encoding: base64
22 | Content-Location: Photo25.jpg
23 | Content-ID: <qbFGyPQAS8>
24 | Content-Disposition: inline
25 |
26 | jamisSqGSIb3DQEHAqCAMIjamisxCzAJBgUrDgMCGgUAMIAGCSqGSjamisEHAQAAoIIFSjCCBUYw
27 | ggQujamisQICBD++ukQwDQYJKojamisNAQEFBQAwMTELMAkGA1UEBhMCRjamisAKBgNVBAoTA1RE
28 | QzEUMBIGjamisxMLVERDIE9DRVMgQ0jamisNMDQwMjI5MTE1OTAxWhcNMDYwMjamisIyOTAxWjCB
29 | gDELMAkGA1UEjamisEsxKTAnBgNVBAoTIEjamisuIG9yZ2FuaXNhdG9yaXNrIHRpbjamisRuaW5=
30 |
31 | --Apple-Mail-13-196941151--
32 |
33 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/mime_emails/raw_email7.eml:
--------------------------------------------------------------------------------
1 | MIME-Version: 1.0 (Apple Message framework v730)
2 | Content-Type: multipart/mixed; boundary=Apple-Mail-13-196941151
3 | Message-Id: <9169D984-4E0B-45EF-82D4-8F5E53AD7012@example.com>
4 | From: foo@example.com
5 | Subject: testing
6 | Date: Mon, 6 Jun 2005 22:21:22 +0200
7 | To: blah@example.com
8 |
9 |
10 | --Apple-Mail-13-196941151
11 | Content-Type: multipart/mixed;
12 | boundary=Apple-Mail-12-196940926
13 |
14 |
15 | --Apple-Mail-12-196940926
16 | Content-Transfer-Encoding: quoted-printable
17 | Content-Type: text/plain;
18 | charset=ISO-8859-1;
19 | delsp=yes;
20 | format=flowed
21 |
22 | This is the first part.
23 |
24 | --Apple-Mail-12-196940926
25 | Content-Transfer-Encoding: 7bit
26 | Content-Type: text/x-ruby-script;
27 | x-unix-mode=0666;
28 | name="test.rb"
29 | Content-Disposition: attachment;
30 | filename=test.rb
31 |
32 | puts "testing, testing"
33 |
34 | --Apple-Mail-12-196940926
35 | Content-Transfer-Encoding: base64
36 | Content-Type: application/pdf;
37 | x-unix-mode=0666;
38 | name="test.pdf"
39 | Content-Disposition: inline;
40 | filename=test.pdf
41 |
42 | YmxhaCBibGFoIGJsYWg=
43 |
44 | --Apple-Mail-12-196940926
45 | Content-Transfer-Encoding: 7bit
46 | Content-Type: text/plain;
47 | charset=US-ASCII;
48 | format=flowed
49 |
50 |
51 |
52 | --Apple-Mail-12-196940926--
53 |
54 | --Apple-Mail-13-196941151
55 | Content-Transfer-Encoding: base64
56 | Content-Type: application/pkcs7-signature;
57 | name=smime.p7s
58 | Content-Disposition: attachment;
59 | filename=smime.p7s
60 |
61 | jamisSqGSIb3DQEHAqCAMIjamisxCzAJBgUrDgMCGgUAMIAGCSqGSjamisEHAQAAoIIFSjCCBUYw
62 | ggQujamisQICBD++ukQwDQYJKojamisNAQEFBQAwMTELMAkGA1UEBhMCRjamisAKBgNVBAoTA1RE
63 | QzEUMBIGjamisxMLVERDIE9DRVMgQ0jamisNMDQwMjI5MTE1OTAxWhcNMDYwMjamisIyOTAxWjCB
64 | gDELMAkGA1UEjamisEsxKTAnBgNVBAoTIEjamisuIG9yZ2FuaXNhdG9yaXNrIHRpbjamisRuaW5=
65 |
66 | --Apple-Mail-13-196941151--
67 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/mime_emails/raw_email_encoded_stack_level_too_deep.eml:
--------------------------------------------------------------------------------
1 | X-Gmail-Received: 220984aec4c4885e060987be043c9363cbef8551
2 | Received: by 10.36.47.16; Tue, 28 Jun 2005 01:02:11 -0700 (PDT)
3 | Message-ID: <89d7557c0506280102495d555f@mail.gmail.com>
4 | Date: Tue, 28 Jun 2005 01:02:11 -0700
5 | From: Gmail Team <gmail-noreply@google.com>
6 | Reply-To: x.y@gmail.com
7 | To: =?ISO-8859-1?Q?Nicolas_Fouch=E9?= <a.b@gmail.com>
8 | Subject: =?ISO-8859-1?Q?Nicolas_Fouch=E9_has_accepted_your_invitation_to_Gmail?=
9 | MIME-Version: 1.0
10 | Content-Type: multipart/alternative;
11 | boundary="----=_Part_976_15222032.1119945731186"
12 |
13 | ------=_Part_976_15222032.1119945731186
14 | Content-Type: text/plain; charset=ISO-8859-1
15 | Content-Transfer-Encoding: quoted-printable
16 | Content-Disposition: inline
17 |
18 | Nicolas Fouch=E9 has accepted your invitation to Gmail and has chosen the=
19 | =20
20 | brand new address x.y@gmail.com. Be one of the first to email Nicolas=
21 | =20
22 | at this new Gmail address--just hit reply and send Nicolas a message.=20
23 | x.y@gmail.com has also been automatically added to your contact list=
24 | =20
25 | so you can stay in touch with Gmail.=20
26 |
27 |
28 | Thanks,=20
29 |
30 | The Gmail Team
31 |
32 | ------=_Part_976_15222032.1119945731186
33 | Content-Type: text/html; charset=ISO-8859-1
34 | Content-Transfer-Encoding: quoted-printable
35 | Content-Disposition: inline
36 |
37 | <html>
38 | <font face=3D"Arial, Helvetica, sans-serif">
39 | <p>Nicolas Fouch=E9 has accepted your invitation to Gmail and has
40 | chosen the brand new address x.y@gmail.com. Be one of the first to =
41 | email=20
42 | Nicolas at this new Gmail address--just hit reply and send=20
43 | Nicolas a message. x.y@gmail.com has also been automatically added =
44 | to
45 | your contact list so you can stay in touch with Gmail.
46 | </p>
47 | <p><br>
48 | Thanks, </p>
49 | <p> The Gmail Team</p>
50 | </font>
51 | </html>
52 |
53 | ------=_Part_976_15222032.1119945731186--
--------------------------------------------------------------------------------
/spec/fixtures/emails/mime_emails/raw_email_with_binary_encoded.eml:
--------------------------------------------------------------------------------
1 | From email_test@me.nowhere
2 | Return-Path: <email_test@me.nowhere>
3 | Received: from omta05sl.mx.bigpond.com by me.nowhere.else with ESMTP id 632BD5758 for <mikel@me.nowhere.else>; Sun, 21 Oct 2007 19:38:21 +1000
4 | Received: from oaamta05sl.mx.bigpond.com by omta05sl.mx.bigpond.com with ESMTP id <20071021093820.HSPC16667.omta05sl.mx.bigpond.com@oaamta05sl.mx.bigpond.com> for <mikel@me.nowhere.else>; Sun, 21 Oct 2007 19:38:20 +1000
5 | Received: from mikel091a by oaamta05sl.mx.bigpond.com with SMTP id <20071021093820.JFMT24025.oaamta05sl.mx.bigpond.com@mikel091a> for <mikel@me.nowhere.else>; Sun, 21 Oct 2007 19:38:20 +1000
6 | Date: Sun, 21 Oct 2007 19:38:13 +1000
7 | From: Mikel Lindsaar <email_test@me.nowhere>
8 | Reply-To: Mikel Lindsaar <email_test@me.nowhere>
9 | To: mikel@me.nowhere
10 | Message-Id: <009601c813c6$19df3510$0437d30a@mikel091a>
11 | Subject: Testing outlook
12 | Subject: Another PDF
13 | MIME-Version: 1.0
14 | Content-Type: multipart/alternative;
15 | boundary=----=_Part_13069834_15179892.1376435426074
16 |
17 |
18 | ------=_Part_13069834_15179892.1376435426074
19 | Content-Type: image/jpeg; name=2013-08-13_19-08-28-1.jpg
20 | Content-Transfer-Encoding: binary
21 | Content-Location: 2013-08-13_19-08-28-1.jpg
22 |
23 | BINARY_CONTENT_GOES_HERE
24 | ------=_Part_13069834_15179892.1376435426074--
25 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/mime_emails/sig_only_email.eml:
--------------------------------------------------------------------------------
1 | Date: Mon, 4 Jun 2007 15:01:31 -0700
2 | From: Test <test@test.lindsaar.net>
3 | To: Mikel <mikel@test.lindsaar.net>
4 | Subject: Re: Testing multipart/signed
5 | Message-ID: <20070604150131.40d4fa1e@reforged>
6 | MIME-Version: 1.0
7 | Content-Type: multipart/signed; boundary=Sig_2GIY2xfzqSADMmu9sKGJqWm;
8 | protocol="application/pgp-signature"; micalg=PGP-SHA1
9 |
10 | --Sig_2GIY2xfzqSADMmu9sKGJqWm
11 | Content-Type: text/plain; charset=US-ASCII
12 | Content-Transfer-Encoding: quoted-printable
13 |
14 | This is random text, not what has been signed below, ie, this sig
15 | email is not signed correctly.
16 |
17 | --Sig_2GIY2xfzqSADMmu9sKGJqWm
18 | Content-Type: application/pgp-signature; name=signature.asc
19 | Content-Disposition: attachment; filename=signature.asc
20 |
21 | -----BEGIN PGP SIGNATURE-----
22 | Version: GnuPG v1.4.6 (GNU/Linux)
23 |
24 | iD8DB1111Iu7dfRchrkBInkRArniAKCue17JOxXBiAZHwLy3uFacU+pmhwCgwzhf
25 | V5YSPv2xmYOA6mJ6oVaasseQ=
26 | =T7p9
27 | -----END PGP SIGNATURE-----
28 |
29 | --Sig_2GIY2xfzqSADMmu9sKGJqWm--
30 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/mime_emails/two_from_in_message.eml:
--------------------------------------------------------------------------------
1 | Return-Path: <test@test.com>
2 | Received: from mail-xxx.google.com (mail-xxx.google.com [0.0.0.0])
3 | by smtp.test.com (Postfix) with ESMTP id xxxx
4 | for <tester@test.com>; Wed, 2 Dec 2009 09:39:57 +0000 (UTC)
5 | Received: by qyk6 with SMTP id 6so3112qyk.3
6 | for <tester@test.com>; Wed, 02 Dec 2009 01:39:53 -0800 (PST)
7 | MIME-Version: 1.0
8 | Received: by 0.0.0.0 with SMTP id xxx.000.0000000000000; Wed,
9 | 02 Dec 2009 01:39:53 -0800 (PST)
10 | In-Reply-To: <8fc5086d0912020131y377ba0ccpf8f14783cfc3014a@test.com>
11 | References: <8fc5086d0912020131y377ba0ccpf8f14783cfc3014a@test.com>
12 | From: Tester 1 <tester1@test.com>
13 | Date: Wed, 2 Dec 2009 22:39:33 +1300
14 | Message-ID: <8fc5086d0912020139y1564ad32jb4f4209fa464f4a6@test.com>
15 | Subject: Sending messages include last little bit
16 | To: tester2@test.com
17 | Content-Type: multipart/alternative; boundary=00c09fa216eb1bfc0a0479bba823
18 |
19 | --00c09fa216eb1bfc0a0479bba823
20 | Content-Type: text/plain; charset=ISO-8859-1
21 |
22 | When sending email:
23 | * From Hotmail you get the ads as well.
24 | * From GMail you also get the person's signature.
25 |
26 | I'm curious, and I might do some digging tomorrow as well, to see if its
27 | possible to strip the last little bit (signature/ads) from email messages.
28 |
29 | --00c09fa216eb1bfc0a0479bba823
30 | Content-Type: text/html; charset=ISO-8859-1
31 | Content-Transfer-Encoding: quoted-printable
32 |
33 | <div class=3D"gmail_quote"><div class=3D"gmail_quote"><div>When sending ema=
34 | il:</div>* From Hotmail you get the ads as well.<div>* Fr=
35 | om GMail you also get the person's signature.</div><div><br></div><div>=
36 | I'm curious, and I might do some digging tomorrow as well, to see if it=
37 | s possible to strip the last little bit (signature/ads) from email messages=
38 | .<br>
39 |
40 | </div></div></div>
41 |
42 | --00c09fa216eb1bfc0a0479bba823--
--------------------------------------------------------------------------------
/spec/fixtures/emails/multi_charset/japanese.eml:
--------------------------------------------------------------------------------
1 | MIME-Version: 1.0
2 | Subject: =?UTF-8?B?44G+44G/44KA44KB44KC?=
3 | From: Mikel Lindsaar <raasdnil@gmail.com>
4 | To: =?UTF-8?B?44G/44GR44KL?= <raasdnil@gmail.com>
5 | Content-Type: text/plain; charset=UTF-8
6 | Content-Transfer-Encoding: base64
7 |
8 | 44GL44GN44GP44GI44GTCgotLSAKaHR0cDovL2xpbmRzYWFyLm5ldC8KUmFpbHMsIFJTcGVjIGFu
9 | ZCBMaWZlIGJsb2cuLi4uCg==
--------------------------------------------------------------------------------
/spec/fixtures/emails/multi_charset/japanese_attachment.eml:
--------------------------------------------------------------------------------
1 | MIME-Version: 1.0
2 | Received: by 10.231.35.72 with HTTP; Fri, 16 Oct 2009 05:39:34 -0700 (PDT)
3 | Date: Fri, 16 Oct 2009 23:39:34 +1100
4 | Delivered-To: raasdnil@gmail.com
5 | Message-ID: <57a815bf0910160539m64240421gb35ea52e101aedbc@mail.gmail.com>
6 | Subject: testing
7 | From: Mikel Lindsaar <raasdnil@gmail.com>
8 | To: Mikel Lindsaar <raasdnil@gmail.com>
9 | Content-Type: multipart/mixed; boundary=00032557395e3572cf04760cb060
10 |
11 | --00032557395e3572cf04760cb060
12 | Content-Type: text/plain; charset=UTF-8
13 |
14 | testing
15 |
16 | --
17 | http://lindsaar.net/
18 | Rails, RSpec and Life blog....
19 |
20 | --00032557395e3572cf04760cb060
21 | Content-Type: text/plain; charset=UTF-8; name="=?UTF-8?B?44Gm44GZ44GoLnR4dA==?="
22 | Content-Disposition: attachment; filename="=?UTF-8?B?44Gm44GZ44GoLnR4dA==?="
23 | Content-Transfer-Encoding: base64
24 | X-Attachment-Id: f_g0uxfl510
25 |
26 | dGhpcyBpcyBhIHRlc3QK44GT44KM44KP44Gm44GZ44Go
27 | --00032557395e3572cf04760cb060--
--------------------------------------------------------------------------------
/spec/fixtures/emails/multi_charset/japanese_iso_2022.eml:
--------------------------------------------------------------------------------
1 | MIME-Version: 1.0
2 | Subject: =?UTF-8?B?44G+44G/44KA44KB44KC?=
3 | From: Mikel Lindsaar <raasdnil@gmail.com>
4 | To: =?UTF-8?B?44G/44GR44KL?= <raasdnil@gmail.com>
5 | Content-Type: text/plain;
6 | charset=iso-2022-jp
7 | Content-Transfer-Encoding: 7bit
8 |
9 | $B$9$_$^$;$s!#(B
10 |
11 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/multi_charset/japanese_shift_jis.eml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikel/mail/d1d65b370b109b98e673a934e8b70a0c1f58cc59/spec/fixtures/emails/multi_charset/japanese_shift_jis.eml
--------------------------------------------------------------------------------
/spec/fixtures/emails/multi_charset/ks_c_5601-1987.eml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikel/mail/d1d65b370b109b98e673a934e8b70a0c1f58cc59/spec/fixtures/emails/multi_charset/ks_c_5601-1987.eml
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/basic_email.eml:
--------------------------------------------------------------------------------
1 | Delivered-To: raasdnil@gmail.com
2 | Received: by 10.140.178.13 with SMTP id a13cs354079rvf;
3 | Fri, 21 Nov 2008 20:05:05 -0800 (PST)
4 | Received: by 10.151.44.15 with SMTP id w15mr2254748ybj.98.1227326704711;
5 | Fri, 21 Nov 2008 20:05:04 -0800 (PST)
6 | Return-Path: <test@lindsaar.net>
7 | Received: from mail11.tpgi.com.au (mail11.tpgi.com.au [203.12.160.161])
8 | by mx.google.com with ESMTP id 10si5117885gxk.81.2008.11.21.20.05.03;
9 | Fri, 21 Nov 2008 20:05:04 -0800 (PST)
10 | Received-SPF: neutral (google.com: 203.12.160.161 is neither permitted nor denied by domain of test@lindsaar.net) client-ip=203.12.160.161;
11 | Authentication-Results: mx.google.com; spf=neutral (google.com: 203.12.160.161 is neither permitted nor denied by domain of test@lindsaar.net) smtp.mail=test@lindsaar.net
12 | X-TPG-Junk-Status: Message not scanned
13 | X-TPG-Antivirus: Passed
14 | Received: from [192.0.0.253] (60-241-138-146.static.tpgi.com.au [60.0.0.146])
15 | by mail11.tpgi.com.au (envelope-from test@lindsaar.net) (8.14.3/8.14.3) with ESMTP id mAM44xew022221
16 | for <raasdnil@gmail.com>; Sat, 22 Nov 2008 15:05:01 +1100
17 | Message-Id: <6B7EC235-5B17-4CA8-B2B8-39290DEB43A3@test.lindsaar.net>
18 | From: Mikel Lindsaar <test@lindsaar.net>
19 | To: Mikel Lindsaar <raasdnil@gmail.com>
20 | Content-Type: text/plain; charset=US-ASCII; format=flowed
21 | Content-Transfer-Encoding: 7bit
22 | MIME-Version: 1.0 (Apple Message framework v929.2)
23 | Subject: Testing 123
24 | Date: Sat, 22 Nov 2008 15:04:59 +1100
25 | X-Mailer: Apple Mail (2.929.2)
26 |
27 | Plain email.
28 |
29 | Hope it works well!
30 |
31 | Mikel
32 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/basic_email_lf.eml:
--------------------------------------------------------------------------------
1 | Delivered-To: raasdnil@gmail.com
2 | Received: by 10.140.178.13 with SMTP id a13cs354079rvf;
3 | Fri, 21 Nov 2008 20:05:05 -0800 (PST)
4 | Received: by 10.151.44.15 with SMTP id w15mr2254748ybj.98.1227326704711;
5 | Fri, 21 Nov 2008 20:05:04 -0800 (PST)
6 | Return-Path: <test@lindsaar.net>
7 | Received: from mail11.tpgi.com.au (mail11.tpgi.com.au [203.12.160.161])
8 | by mx.google.com with ESMTP id 10si5117885gxk.81.2008.11.21.20.05.03;
9 | Fri, 21 Nov 2008 20:05:04 -0800 (PST)
10 | Received-SPF: neutral (google.com: 203.12.160.161 is neither permitted nor denied by domain of test@lindsaar.net) client-ip=203.12.160.161;
11 | Authentication-Results: mx.google.com; spf=neutral (google.com: 203.12.160.161 is neither permitted nor denied by domain of test@lindsaar.net) smtp.mail=test@lindsaar.net
12 | X-TPG-Junk-Status: Message not scanned
13 | X-TPG-Antivirus: Passed
14 | Received: from [192.0.0.253] (60-241-138-146.static.tpgi.com.au [60.0.0.146])
15 | by mail11.tpgi.com.au (envelope-from test@lindsaar.net) (8.14.3/8.14.3) with ESMTP id mAM44xew022221
16 | for <raasdnil@gmail.com>; Sat, 22 Nov 2008 15:05:01 +1100
17 | Message-Id: <6B7EC235-5B17-4CA8-B2B8-39290DEB43A3@test.lindsaar.net>
18 | From: Mikel Lindsaar <test@lindsaar.net>
19 | To: Mikel Lindsaar <raasdnil@gmail.com>
20 | Content-Type: text/plain; charset=US-ASCII; format=flowed
21 | Content-Transfer-Encoding: 7bit
22 | MIME-Version: 1.0 (Apple Message framework v929.2)
23 | Subject: Testing 123
24 | Date: Sat, 22 Nov 2008 15:04:59 +1100
25 | X-Mailer: Apple Mail (2.929.2)
26 |
27 | Plain email.
28 |
29 | Hope it works well!
30 |
31 | Mikel
32 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/mix_caps_content_type.eml:
--------------------------------------------------------------------------------
1 | From joe@company.com Fri Feb 19 08:41:30 2010
2 | From: Big Bug bb@bug.com
3 | To: rubymail@ruby-lang.org
4 | Subject: undef method parameter bug
5 | Date: Fri, 19 Feb 2010 10:08:29 +0300
6 | MIME-Version: 1.0
7 | Content-Type: Text/Plain; charset="iso-8859-1"
8 | Content-Transfer-Encoding: quoted-printable
9 | Message-Id: 201002191008.30117.foo.bar@company.com
10 |
11 | foo bar
12 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/raw_email.eml:
--------------------------------------------------------------------------------
1 | From jamis_buck@byu.edu Mon May 2 16:07:05 2005
2 | MIME-Version: 1.0 (Apple Message framework v622)
3 | Content-Transfer-Encoding: base64
4 | Message-Id: <d3b8cf8e49f04480850c28713a1f473e@37signals.com>
5 | Content-Type: text/plain;
6 | charset=EUC-KR;
7 | format=flowed
8 | To: willard15georgina@jamis.backpackit.com
9 | From: Jamis Buck <jamis@37signals.com>
10 | Subject: =?EUC-KR?Q?NOTE:_=C7=D1=B1=B9=B8=BB=B7=CE_=C7=CF=B4=C2_=B0=CD?=
11 | Date: Mon, 2 May 2005 16:07:05 -0600
12 |
13 | tOu6zrrQwMcguLbC+bChwfa3ziwgv+y4rrTCIMfPs6q01MC7ILnPvcC0z7TZLg0KDQrBpiDAzLin
14 | wLogSmFtaXPA1LTPtNku
15 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/raw_email10.eml:
--------------------------------------------------------------------------------
1 | Return-Path: <xxx@xxxx.xxx>
2 | Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id C1B953B4CB6 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:05 -0500
3 | Received: from SMS-GTYxxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id ca for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:04 -0500
4 | Received: from xxx.xxxx.xxx by SMS-GTYxxx.xxxx.xxx with ESMTP id j4AKR3r23323 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:03 -0500
5 | Date: Tue, 10 May 2005 15:27:03 -0500
6 | From: xxx@xxxx.xxx
7 | Sender: xxx@xxxx.xxx
8 | To: xxxxxxxxxxx@xxxx.xxxx.xxx
9 | Message-Id: <xxx@xxxx.xxx>
10 | X-Original-To: xxxxxxxxxxx@xxxx.xxxx.xxx
11 | Delivered-To: xxx@xxxx.xxx
12 | Importance: normal
13 | Content-Type: text/plain; charset=X-UNKNOWN
14 |
15 | Test test. Hi. Waving. m
16 |
17 | ----------------------------------------------------------------
18 | Sent via Bell Mobility's Text Messaging service.
19 | Envoyé par le service de messagerie texte de Bell Mobilité.
20 | ----------------------------------------------------------------
21 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/raw_email5.eml:
--------------------------------------------------------------------------------
1 | Return-Path: <xxx@xxxx.xxx>
2 | Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id C1B953B4CB6 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:05 -0500
3 | Received: from SMS-GTYxxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id ca for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:04 -0500
4 | Received: from xxx.xxxx.xxx by SMS-GTYxxx.xxxx.xxx with ESMTP id j4AKR3r23323 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:03 -0500
5 | Date: Tue, 10 May 2005 15:27:03 -0500
6 | From: xxx@xxxx.xxx
7 | Sender: xxx@xxxx.xxx
8 | To: xxxxxxxxxxx@xxxx.xxxx.xxx
9 | Message-Id: <xxx@xxxx.xxx>
10 | X-Original-To: xxxxxxxxxxx@xxxx.xxxx.xxx
11 | Delivered-To: xxx@xxxx.xxx
12 | Importance: normal
13 |
14 | Test test. Hi. Waving. m
15 |
16 | ----------------------------------------------------------------
17 | Sent via Bell Mobility's Text Messaging service.
18 | Envoyé par le service de messagerie texte de Bell Mobilité.
19 | ----------------------------------------------------------------
20 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/raw_email6.eml:
--------------------------------------------------------------------------------
1 | Return-Path: <xxx@xxxx.xxx>
2 | Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id C1B953B4CB6 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:05 -0500
3 | Received: from SMS-GTYxxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id ca for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:04 -0500
4 | Received: from xxx.xxxx.xxx by SMS-GTYxxx.xxxx.xxx with ESMTP id j4AKR3r23323 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:03 -0500
5 | Date: Tue, 10 May 2005 15:27:03 -0500
6 | From: xxx@xxxx.xxx
7 | Sender: xxx@xxxx.xxx
8 | To: xxxxxxxxxxx@xxxx.xxxx.xxx
9 | Message-Id: <xxx@xxxx.xxx>
10 | X-Original-To: xxxxxxxxxxx@xxxx.xxxx.xxx
11 | Delivered-To: xxx@xxxx.xxx
12 | Importance: normal
13 | Content-Type: text/plain; charset=us-ascii
14 |
15 | Test test. Hi. Waving. m
16 |
17 | ----------------------------------------------------------------
18 | Sent via Bell Mobility's Text Messaging service.
19 | Envoyé par le service de messagerie texte de Bell Mobilité.
20 | ----------------------------------------------------------------
21 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/raw_email8.eml:
--------------------------------------------------------------------------------
1 | From xxxxxxxxx.xxxxxxx@gmail.com Sun May 8 19:07:09 2005
2 | Return-Path: <xxxxxxxxx.xxxxxxx@gmail.com>
3 | Message-ID: <e85734b90505081209eaaa17b@mail.gmail.com>
4 | Date: Sun, 8 May 2005 14:09:11 -0500
5 | From: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
6 | Reply-To: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
7 | To: xxxxx xxxx <xxxxx@xxxxxxxxx.com>
8 | Subject: Fwd: Signed email causes file attachments
9 | In-Reply-To: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
10 | MIME-Version: 1.0
11 | Content-Type: multipart/mixed;
12 | boundary="----=_Part_5028_7368284.1115579351471"
13 | References: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
14 |
15 | ------=_Part_5028_7368284.1115579351471
16 | Content-Type: text/plain; charset=ISO-8859-1
17 | Content-Transfer-Encoding: quoted-printable
18 | Content-Disposition: inline
19 |
20 | We should not include these files or vcards as attachments.
21 |
22 | ---------- Forwarded message ----------
23 | From: xxxxx xxxxxx <xxxxxxxx@xxx.com>
24 | Date: May 8, 2005 1:17 PM
25 | Subject: Signed email causes file attachments
26 | To: xxxxxxx@xxxxxxxxxx.com
27 |
28 |
29 | Hi,
30 |
31 | Test attachments oddly encoded with japanese charset.
32 |
33 |
34 | ------=_Part_5028_7368284.1115579351471
35 | Content-Type: application/octet-stream; name*=iso-2022-jp'ja'01%20Quien%20Te%20Dij%8aat.%20Pitbull.mp3
36 | Content-Transfer-Encoding: base64
37 | Content-Disposition: attachment
38 |
39 | MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIGFDCCAs0w
40 | ggI2oAMCAQICAw5c+TANBgkqhkiG9w0BAQQFADBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh
41 | d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVt
42 | YWlsIElzc3VpbmcgQ0EwHhcNMDUwMzI5MDkzOTEwWhcNMDYwMzI5MDkzOTEwWjBCMR8wHQYDVQQD
43 | ExZUaGF3dGUgRnJlZW1haWwgTWVtYmVyMR8wHQYJKoZIhvcNAQkBFhBzbWhhdW5jaEBtYWMuY29t
44 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn90dPsYS3LjfMY211OSYrDQLzwNYPlAL
45 | 7+/0XA+kdy8/rRnyEHFGwhNCDmg0B6pxC7z3xxJD/8GfCd+IYUUNUQV5m9MkxfP9pTVXZVIYLaBw
46 | ------=_Part_5028_7368284.1115579351471--
47 |
48 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/raw_email_double_at_in_header.eml:
--------------------------------------------------------------------------------
1 | From jamis_buck@byu.edu Mon May 2 16:07:05 2005
2 | MIME-Version: 1.0 (Apple Message framework v622)
3 | Content-Transfer-Encoding: base64
4 | Message-Id: <d3b8cf8e49f0448085@0c28713a1@f473e@37signals.com>
5 | Content-Type: text/plain;
6 | charset=EUC-KR;
7 | format=flowed
8 | To: willard15georgina@jamis.backpackit.com
9 | From: Jamis Buck <jamis@37signals.com>
10 | Subject: =?EUC-KR?Q?NOTE:_=C7=D1=B1=B9=B8=BB=B7=CE_=C7=CF=B4=C2_=B0=CD?=
11 | Date: Mon, 2 May 2005 16:07:05 -0600
12 |
13 | tOu6zrrQwMcguLbC+bChwfa3ziwgv+y4rrTCIMfPs6q01MC7ILnPvcC0z7TZLg0KDQrBpiDAzLin
14 | wLogSmFtaXPA1LTPtNku
15 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/raw_email_incorrect_header.eml:
--------------------------------------------------------------------------------
1 | Received: from xxx.xxx.xxx ([xxx.xxx.xxx.xxx] verified)
2 | by xxx.com (CommuniGate Pro SMTP 4.2.8)
3 | with SMTP id 2532598 for xxx@xxx.com; Wed, 23 Feb 2005 17:51:49 -0500
4 | Received-SPF: softfail
5 | receiver=xxx.com; client-ip=xxx.xxx.xxx.xxx; envelope-from=xxx@xxx.xxx
6 | quite Delivered-To: xxx@xxx.xxx
7 | Received: by xxx.xxx.xxx (Wostfix, from userid xxx)
8 | id 0F87F333; Wed, 23 Feb 2005 16:16:17 -0600
9 | Date: Wed, 23 Feb 2005 18:20:17 -0400
10 | From: "xxx xxx" <xxx@xxx.xxx>
11 | Message-ID: <4D6AA7EB.6490534@xxx.xxx>
12 | To: xxx@xxx.com
13 | Subject: Stop adware/spyware once and for all.
14 | X-Scanned-By: MIMEDefang 2.11 (www dot roaringpenguin dot com slash mimedefang)
15 |
16 | You are infected with:
17 | Ad Ware and Spy Ware
18 |
19 | Get your free scan and removal download now,
20 | before it gets any worse.
21 |
22 | http://xxx.xxx.info?aid=3D13&?stat=3D4327kdzt
23 |
24 |
25 |
26 |
27 | no more? (you will still be infected)
28 | http://xxx.xxx.info/discon/?xxx@xxx.com
29 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/raw_email_multiple_from.eml:
--------------------------------------------------------------------------------
1 | Delivered-To: tim@powerupdev.com
2 | Return-Path: <www-data@mangaverde.net>
3 | To: tim@powerupdev.com concierge@powerupdev.com
4 | From: tim@powerupdev.com concierge@powerupdev.com
5 | Subject: /home/svn/public/minebox revision 214
6 | Reply-to: tim@powerupdev.com concierge@powerupdev.com
7 | Message-Id: <20071022234523.5BD8E86D2@mangaverde.net>
8 | Date: Mon, 22 Oct 2007 23:45:23 +0000 (UTC)
9 |
10 | <p><b>recordkick</b> 2007-10-22 23:45:23 +0000 (Mon, 22 Oct 2007)</p><p>test
11 | subversion<br>
12 | </p><hr noshade><pre><font color=\"gray\">Modified:
13 | trunk/README
14 | ===================================================================
15 | --- trunk/README\t2007-10-22
16 | 23:41:34 UTC (rev 213)
17 | +++ trunk/README\t2007-10-22 23:45:23 UTC (rev 214)
18 | @@ -1,5 +1,5 @@
19 | == Welcome
20 | to Rails
21 | -Test
22 | +Tedst
23 | Rails is a web-application and persistence framework that includes everything
24 | needed
25 | to create database-backed web-applications according to the
26 | Model-View-Control pattern of separation. This pattern
27 | splits the view (also
28 |
29 | </font>
30 | </pre>
31 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/raw_email_quoted_with_0d0a.eml:
--------------------------------------------------------------------------------
1 | MIME-Version: 1.0 (Apple Message framework v730)
2 | Message-Id: <9169D984-4E0B-45EF-82D4-8F5E53AD7012@example.com>
3 | From: foo@example.com
4 | Subject: testing
5 | Date: Mon, 6 Jun 2005 22:21:22 +0200
6 | To: blah@example.com
7 | Content-Transfer-Encoding: quoted-printable
8 | Content-Type: text/plain
9 |
10 | A fax has arrived from remote ID ''.=0D=0A-----------------------=
11 | -------------------------------------=0D=0ATime: 3/9/2006 3:50:52=
12 | PM=0D=0AReceived from remote ID: =0D=0AInbound user ID XXXXXXXXXX, r=
13 | outing code XXXXXXXXX=0D=0AResult: (0/352;0/0) Successful Send=0D=0AP=
14 | age record: 1 - 1=0D=0AElapsed time: 00:58 on channel 11=0D=0A
15 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/raw_email_reply.eml:
--------------------------------------------------------------------------------
1 | Return-Path: <xxxxxxxx@xxx.org>
2 | Received: from me ([unix socket])
3 | by xxxxx1.xxxx.net (Cyrus v2.2.12) with LMTPA;
4 | Sun, 18 Nov 2007 00:56:33 -0800
5 | Received: from smtp.xxxx.org (unknown [127.0.0.1])
6 | by xxxxx1.xxxx.net (Postfix) with ESMTP id F128477EB5;
7 | Sun, 18 Nov 2007 00:56:32 -0800 (PST)
8 | Received: from omta02sl.mx.bigpond.com (omta02sl.mx.bigpond.com [144.140.93.154])
9 | by smtp.xxxx.org (Postfix) with ESMTP id 2D567ACC08;
10 | Sun, 18 Nov 2007 00:56:28 -0800 (PST)
11 | Received: from oaamta05sl.mx.bigpond.com ([124.183.219.10])
12 | by omta02sl.mx.bigpond.com with ESMTP
13 | id <20071118085627.YVPI22254.omta02sl.mx.bigpond.com@oaamta05sl.mx.bigpond.com>;
14 | Sun, 18 Nov 2007 08:56:27 +0000
15 | Received: from [10.0.0.1] (really [124.183.219.10])
16 | by oaamta05sl.mx.bigpond.com with ESMTP
17 | id <20071118085627.TQWF6995.oaamta05sl.mx.bigpond.com@[10.0.0.1]>;
18 | Sun, 18 Nov 2007 08:56:27 +0000
19 | Message-ID: <473FFE27.20003@xxx.org>
20 | Date: Sun, 18 Nov 2007 19:56:07 +1100
21 | From: Testing <xxxxxxxx@xxx.org>
22 | User-Agent: Mozilla Thunderbird 1.0.6 (Windows/20050716)
23 | X-Accept-Language: en-us, en
24 | MIME-Version: 1.0
25 | To: Mikel Lindsaar <mikel@xxxx.net>
26 | Subject: Re: Test reply email
27 | References: <473FF3B8.9020707@xxx.org> <348F04F142D69C21-291E56D292BC@xxxx.net>
28 | In-Reply-To: <348F04F142D69C21-291E56D292BC@xxxx.net>
29 | Content-Type: text/plain; charset=US-ASCII; format=flowed
30 | Content-Transfer-Encoding: 7bit
31 |
32 | Message body
33 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/raw_email_simple.eml:
--------------------------------------------------------------------------------
1 | From mike@nowhere.com
2 | Return-Path: <mikel@nowhere.com>
3 | Received: from mikel091a by oaamta05sl.mx.bigpond.com with SMTP id <20071021093820.JFMT24025.oaamta05sl.mx.bigpond.com@mikel091a> for <mikel@nowhere.com.else>; Sun, 21 Oct 2007 19:38:20 +1000
4 | Date: Sun, 21 Oct 2007 19:38:13 +1000
5 | From: Mikel Lindsaar <mikel@nowhere.com>
6 | To: Mikel <mikel@somewhere.com>
7 | Message-Id: <009601c813c6$19df3510$0437d30a@mikel091a>
8 | Subject: Testing outlook
9 |
10 | Hello Mikel
11 |
12 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/raw_email_string_in_date_field.eml:
--------------------------------------------------------------------------------
1 | From mikel@me.com Mon May 2 16:07:05 2005
2 | MIME-Version: 1.0 (Apple Message framework v622)
3 | Received: from jsj1wlrmd001.webex.com (by jsj1wlrmd001.webex.com
4 | (8.12.10/8.12.11) with ESMTP id m8MKKPTs022429
5 | for <xxxx@example.com>; Mon, 22 Sep 2008 20:20:25 GMT
6 | Content-Transfer-Encoding: base64
7 | Message-Id: <d3b8cf8e49f04480850c28713a1f473e@lindsaar.net>
8 | Content-Type: text/plain;
9 | charset=EUC-KR;
10 | format=flowed
11 | To: bob@bob.com
12 | From: mikel@me.com
13 | Subject: =?EUC-KR?Q?NOTE:_=C7=D1=B1=B9=B8=BB=B7=CE_=C7=CF=B4=C2_=B0=CD?=
14 | Date: Sat, 20 Sep 2008 20:04:30 +0300 (ùòåï ÷éõ éøåùìéí)
15 |
16 | tOu6zrrQwMcguLbC+bChwfa3ziwgv+y4rrTCIMfPs6q01MC7ILnPvcC0z7TZLg0KDQrBpiDAzLin
17 | wLogSmFtaXPA1LTPtNku
18 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/raw_email_trailing_dot.eml:
--------------------------------------------------------------------------------
1 | Delivered-To: xxx@xxx.com
2 | Received: by 10.67.31.8 with SMTP id i8cs1195ugj;
3 | Mon, 22 Sep 2008 13:45:18 -0700 (PDT)
4 | Received: by 10.100.207.5 with SMTP id e5mr3483815ang.104.1222110393505;
5 | Mon, 22 Sep 2008 12:06:33 -0700 (PDT)
6 | Return-Path: <noreply@rubyforge.org>
7 | Received: from rubyforge.org (rubyforge.org [205.234.109.19])
8 | by mx.google.com with ESMTP id c2si899474ana.10.2008.09.22.12.06.28;
9 | Mon, 22 Sep 2008 12:06:33 -0700 (PDT)
10 | Received-SPF: pass (google.com: best guess record for domain of noreply@rubyforge.org designates 205.234.109.19 as permitted sender) client-ip=205.234.109.19;
11 | Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of noreply@rubyforge.org designates 205.234.109.19 as permitted sender) smtp.mail=noreply@rubyforge.org
12 | Received: by rubyforge.org (Postfix, from userid 502)
13 | id 8FB1518581AC; Mon, 22 Sep 2008 15:06:28 -0400 (EDT)
14 | To: noreply@rubyforge.org
15 | From: Sandy M. <noreply@rubyforge.org>
16 | Subject: [skynet-help][60666] How are intermediate files handled in SkyNet?
17 | Content-type: text/plain; charset=UTF-8
18 | Message-Id: <20080922190628.8FB1518581AC@rubyforge.org>
19 | Date: Mon, 22 Sep 2008 15:06:28 -0400 (EDT)
20 |
21 | Testing, testing, 123.
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/raw_email_with_at_display_name.eml:
--------------------------------------------------------------------------------
1 | Delivered-To: raasdnil@gmail.com
2 | Received: by 10.140.178.13 with SMTP id a13cs354079rvf;
3 | Fri, 21 Nov 2008 20:05:05 -0800 (PST)
4 | Received: by 10.151.44.15 with SMTP id w15mr2254748ybj.98.1227326704711;
5 | Fri, 21 Nov 2008 20:05:04 -0800 (PST)
6 | Return-Path: <test@lindsaar.net>
7 | Received: from mail11.tpgi.com.au (mail11.tpgi.com.au [203.12.160.161])
8 | by mx.google.com with ESMTP id 10si5117885gxk.81.2008.11.21.20.05.03;
9 | Fri, 21 Nov 2008 20:05:04 -0800 (PST)
10 | Received-SPF: neutral (google.com: 203.12.160.161 is neither permitted nor denied by domain of test@lindsaar.net) client-ip=203.12.160.161;
11 | Authentication-Results: mx.google.com; spf=neutral (google.com: 203.12.160.161 is neither permitted nor denied by domain of test@lindsaar.net) smtp.mail=test@lindsaar.net
12 | X-TPG-Junk-Status: Message not scanned
13 | X-TPG-Antivirus: Passed
14 | Received: from [192.0.0.253] (60-241-138-146.static.tpgi.com.au [60.0.0.146])
15 | by mail11.tpgi.com.au (envelope-from test@lindsaar.net) (8.14.3/8.14.3) with ESMTP id mAM44xew022221
16 | for <raasdnil@gmail.com>; Sat, 22 Nov 2008 15:05:01 +1100
17 | Message-Id: <6B7EC235-5B17-4CA8-B2B8-39290DEB43A3@test.lindsaar.net>
18 | From: Mikel Lindsaar <test@lindsaar.net>, jack@lindsar.com
19 | To: smith@gmail.com, Mikel@Lindsaar <raasdnil@gmail.com>, tom@gmail.com
20 | Content-Type: text/plain; charset=US-ASCII; format=flowed
21 | Content-Transfer-Encoding: 7bit
22 | MIME-Version: 1.0 (Apple Message framework v929.2)
23 | Subject: Testing 123
24 | Date: Sat, 22 Nov 2008 15:04:59 +1100
25 | X-Mailer: Apple Mail (2.929.2)
26 |
27 | Plain email.
28 |
29 | Hope it works well!
30 |
31 | Mikel
32 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/plain_emails/raw_email_with_partially_quoted_subject.eml:
--------------------------------------------------------------------------------
1 | From jamis@37signals.com Mon May 2 16:07:05 2005
2 | MIME-Version: 1.0 (Apple Message framework v622)
3 | Content-Transfer-Encoding: base64
4 | Message-Id: <d3b8cf8e49f04480850c28713a1f473e@37signals.com>
5 | Content-Type: text/plain;
6 | charset=EUC-KR;
7 | format=flowed
8 | To: jamis@37signals.com
9 | From: Jamis Buck <jamis@37signals.com>
10 | Subject: Re: Test: =?UTF-8?B?Iua8ouWtlyI=?= mid =?UTF-8?B?Iua8ouWtlyI=?= tail
11 | Date: Mon, 2 May 2005 16:07:05 -0600
12 |
13 | tOu6zrrQwMcguLbC+bChwfa3ziwgv+y4rrTCIMfPs6q01MC7ILnPvcC0z7TZLg0KDQrBpiDAzLin
14 | wLogSmFtaXPA1LTPtNku
15 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/rfc2822/example01.eml:
--------------------------------------------------------------------------------
1 | From: John Doe <jdoe@machine.example>
2 | To: Mary Smith <mary@example.net>
3 | Subject: Saying Hello
4 | Date: Fri, 21 Nov 1997 09:55:06 -0600
5 | Message-ID: <1234@local.machine.example>
6 |
7 | This is a message just to say hello.
8 | So, "Hello".
9 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/rfc2822/example02.eml:
--------------------------------------------------------------------------------
1 | From: John Doe <jdoe@machine.example>
2 | Sender: Michael Jones <mjones@machine.example>
3 | To: Mary Smith <mary@example.net>
4 | Subject: Saying Hello
5 | Date: Fri, 21 Nov 1997 09:55:06 -0600
6 | Message-ID: <1234@local.machine.example>
7 |
8 | This is a message just to say hello.
9 | So, "Hello".
10 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/rfc2822/example03.eml:
--------------------------------------------------------------------------------
1 | From: "Joe Q. Public" <john.q.public@example.com>
2 | To: Mary Smith <mary@x.test>, jdoe@example.org, Who? <one@y.test>
3 | Cc: <boss@nil.test>, "Giant; \"Big\" Box" <sysservices@example.net>
4 | Date: Tue, 1 Jul 2003 10:52:37 +0200
5 | Message-ID: <5678.21-Nov-1997@example.com>
6 |
7 | Hi everyone.
8 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/rfc2822/example04.eml:
--------------------------------------------------------------------------------
1 | From: Pete <pete@silly.example>
2 | To: A Group:Chris Jones <c@a.test>,joe@where.test,John <jdoe@one.test>;
3 | Cc: Undisclosed recipients:;
4 | Date: Thu, 13 Feb 1969 23:32:54 -0330
5 | Message-ID: <testabcd.1234@silly.example>
6 |
7 | Testing.
8 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/rfc2822/example05.eml:
--------------------------------------------------------------------------------
1 | From: John Doe <jdoe@machine.example>
2 | To: Mary Smith <mary@example.net>
3 | Subject: Saying Hello
4 | Date: Fri, 21 Nov 1997 09:55:06 -0600
5 | Message-ID: <1234@local.machine.example>
6 |
7 | This is a message just to say hello.
8 | So, "Hello".
9 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/rfc2822/example06.eml:
--------------------------------------------------------------------------------
1 | From: Mary Smith <mary@example.net>
2 | To: John Doe <jdoe@machine.example>
3 | Reply-To: "Mary Smith: Personal Account" <smith@home.example>
4 | Subject: Re: Saying Hello
5 | Date: Fri, 21 Nov 1997 10:01:10 -0600
6 | Message-ID: <3456@example.net>
7 | In-Reply-To: <1234@local.machine.example>
8 | References: <1234@local.machine.example>
9 |
10 | This is a reply to your hello.
11 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/rfc2822/example07.eml:
--------------------------------------------------------------------------------
1 | To: "Mary Smith: Personal Account" <smith@home.example>
2 | From: John Doe <jdoe@machine.example>
3 | Subject: Re: Saying Hello
4 | Date: Fri, 21 Nov 1997 11:00:00 -0600
5 | Message-ID: <abcd.1234@local.machine.tld>
6 | In-Reply-To: <3456@example.net>
7 | References: <1234@local.machine.example> <3456@example.net>
8 |
9 | This is a reply to your reply.
10 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/rfc2822/example08.eml:
--------------------------------------------------------------------------------
1 | Resent-From: Mary Smith <mary@example.net>
2 | Resent-To: Jane Brown <j-brown@other.example>
3 | Resent-Date: Mon, 24 Nov 1997 14:22:01 -0800
4 | Resent-Message-ID: <78910@example.net>
5 | From: John Doe <jdoe@machine.example>
6 | To: Mary Smith <mary@example.net>
7 | Subject: Saying Hello
8 | Date: Fri, 21 Nov 1997 09:55:06 -0600
9 | Message-ID: <1234@local.machine.example>
10 |
11 | This is a message just to say hello.
12 | So, "Hello".
13 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/rfc2822/example09.eml:
--------------------------------------------------------------------------------
1 | Received: from x.y.test
2 | by example.net
3 | via TCP
4 | with ESMTP
5 | id ABC12345
6 | for <mary@example.net>; 21 Nov 1997 10:05:43 -0600
7 | Received: from machine.example by x.y.test; 21 Nov 1997 10:01:22 -0600
8 | From: John Doe <jdoe@machine.example>
9 | To: Mary Smith <mary@example.net>
10 | Subject: Saying Hello
11 | Date: Fri, 21 Nov 1997 09:55:06 -0600
12 | Message-ID: <1234@local.machine.example>
13 |
14 | This is a message just to say hello.
15 | So, "Hello".
16 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/rfc2822/example10.eml:
--------------------------------------------------------------------------------
1 | From: Pete(A wonderful \) chap) <pete(his account)@silly.test(his host)>
2 | To:A Group(Some people)
3 | :Chris Jones <c@(Chris's host.)public.example>,
4 | joe@example.org,
5 | John <jdoe@one.test> (my dear friend); (the end of the group)
6 | Cc:(Empty list)(start)Undisclosed recipients :(nobody(that I know)) ;
7 | Date: Thu,
8 | 13
9 | Feb
10 | 1969
11 | 23:32
12 | -0330 (Newfoundland Time)
13 | Message-ID: <testabcd.1234@silly.test>
14 |
15 | Testing.
16 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/rfc2822/example11.eml:
--------------------------------------------------------------------------------
1 | From: Joe Q. Public <john.q.public@example.com>
2 | To: Mary Smith <@machine.tld:mary@example.net>, , jdoe@test . example
3 | Date: Tue, 1 Jul 2003 10:52:37 +0200
4 | Message-ID: <5678.21-Nov-1997@example.com>
5 |
6 | Hi everyone.
7 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/rfc2822/example12.eml:
--------------------------------------------------------------------------------
1 | From: John Doe <jdoe@machine.example>
2 | To: Mary Smith <mary@example.net>
3 | Subject: Saying Hello
4 | Date: 21 Nov 97 09:55:06 GMT
5 | Message-ID: <1234@local.machine.example>
6 |
7 | This is a message just to say hello.
8 | So, "Hello".
9 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/rfc2822/example13.eml:
--------------------------------------------------------------------------------
1 | From : John Doe <jdoe@machine(comment). example>
2 | To : Mary Smith
3 | __
4 | <mary@example.net>
5 | Subject : Saying Hello
6 | Date : Fri, 21 Nov 1997 09(comment): 55 : 06 -0600
7 | Message-ID : <1234 @ local(blah) .machine .example>
8 |
9 | This is a message just to say hello.
10 | So, "Hello".
11 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/rfc2822/example14.eml:
--------------------------------------------------------------------------------
1 | From test@example.com Mon Aug 22 09:45:15 2011
2 | Date: Fri, 19 Aug 2011 10:47:17 +0900
3 | From: Atsushi Yoshida <atsushi@example.com>
4 | Reply-To: rudeboyjet@gmail.com
5 | Subject: Re: TEST
6 |
7 | =?ISO-2022-JP?B?GyRCJUYlOSVIGyhC?=
8 | =?ISO-2022-JP?B?GyRCJUYlOSVIGyhC?=
9 | To: rudeboyjet@gmail.com
10 | Message-Id: <0CC5E11ED2C1D@example.com>
11 | In-Reply-To: <rid_5582199198@msgid.example.com>
12 | MIME-Version: 1.0
13 | Content-Type: text/plain; charset=iso-2022-jp
14 | Content-Transfer-Encoding: 7bit
15 |
16 | Hello
17 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/rfc6532/utf8_headers.eml:
--------------------------------------------------------------------------------
1 | From: "Jöhn Doe" <jdöe@mächine.example>
2 | To: "Märy Smith" <märy@exämple.net>
3 | Subject: Säying Hello
4 |
5 | body
6 |
--------------------------------------------------------------------------------
/spec/fixtures/emails/sample_output_multipart:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikel/mail/d1d65b370b109b98e673a934e8b70a0c1f58cc59/spec/fixtures/emails/sample_output_multipart
--------------------------------------------------------------------------------
/spec/mail/core_extensions_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'spec_helper'
4 |
5 | RSpec.describe Object do
6 |
7 | end
8 |
--------------------------------------------------------------------------------
/spec/mail/elements/date_time_element_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'spec_helper'
3 |
4 | RSpec.describe Mail::DateTimeElement do
5 |
6 | it "should parse a date" do
7 | date_text = 'Wed, 27 Apr 2005 14:15:31 -0700'
8 | expect { Mail::DateTimeElement.new(date_text) }.not_to raise_error
9 | end
10 |
11 | it "should raise an error if the input is nil" do
12 | date_text = nil
13 | expect { Mail::DateTimeElement.new(date_text) }.to raise_error(Mail::Field::ParseError)
14 | end
15 |
16 | it "should raise an error if the input is useless" do
17 | date_text = '""""""""""""""""'
18 | expect { Mail::DateTimeElement.new(date_text) }.to raise_error(Mail::Field::ParseError)
19 | end
20 |
21 | end
22 |
--------------------------------------------------------------------------------
/spec/mail/elements/envelope_from_element_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'spec_helper'
3 |
4 | RSpec.describe Mail::EnvelopeFromElement do
5 |
6 | describe "parsing a from envelope string" do
7 | it "should parse a full field" do
8 | expect { Mail::EnvelopeFromElement.new("mikel@test.lindsaar.net Mon Aug 7 00:39:21 2009") }.not_to raise_error
9 | end
10 |
11 | it "should parse a full field with a double digit day" do
12 | expect { Mail::EnvelopeFromElement.new("mikel@test.lindsaar.net Mon Aug 17 00:39:21 2009") }.not_to raise_error
13 | end
14 |
15 | it "should parse a full field with a single space day" do
16 | expect { Mail::EnvelopeFromElement.new("mikel@test.lindsaar.net Mon Aug 17 00:39:21 2009") }.not_to raise_error
17 | end
18 |
19 | it "should parse a null sender, when specified as <>" do
20 | expect { Mail::EnvelopeFromElement.new("<> Mon Aug 17 00:39:21 2009") }.not_to raise_error
21 | end
22 |
23 | it "should parse a null sender, with a single space day" do
24 | expect { Mail::EnvelopeFromElement.new("<> Mon Aug 17 00:39:21 2009") }.not_to raise_error
25 | end
26 | end
27 |
28 | describe "accessor methods" do
29 | it "should return the address" do
30 | envelope = Mail::EnvelopeFromElement.new("mikel@test.lindsaar.net Mon Aug 17 00:39:21 2009")
31 | expect(envelope.address).to eq "mikel@test.lindsaar.net"
32 | end
33 |
34 | it "should return the date_time" do
35 | envelope = Mail::EnvelopeFromElement.new("mikel@test.lindsaar.net Mon Aug 17 00:39:21 2009")
36 | expect(envelope.date_time).to eq ::DateTime.parse("Mon Aug 17 00:39:21 2009")
37 | end
38 | end
39 |
40 | describe 'formatting' do
41 | it 'should format delivery date using UNIX ctime style' do
42 | time = Time.now
43 | envelope = Mail::EnvelopeFromElement.new("mikel@test.lindsaar.net #{time.ctime}")
44 | expect(envelope.to_s).to eq "mikel@test.lindsaar.net #{time.ctime}"
45 | end
46 | end
47 |
48 | end
49 |
--------------------------------------------------------------------------------
/spec/mail/elements/message_ids_element_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'spec_helper'
3 |
4 | RSpec.describe Mail::MessageIdsElement do
5 |
6 | it "should parse a message_id" do
7 | msg_id_text = '<1234@test.lindsaar.net>'
8 | expect { Mail::MessageIdsElement.new(msg_id_text) }.not_to raise_error
9 | end
10 |
11 | it "should parse multiple message_ids" do
12 | msg_id_text = '<1234@test.lindsaar.net> <1234@test.lindsaar.net>'
13 | expect { Mail::MessageIdsElement.new(msg_id_text) }.not_to raise_error
14 | end
15 |
16 | it "treats nil as an empty list" do
17 | element = Mail::MessageIdsElement.new(nil)
18 | expect(element.message_ids).to eq []
19 | expect(element.message_id).to be_nil
20 | end
21 |
22 | it "should raise an error if the input is useless" do
23 | msg_id_text = '""""""""""""""""'
24 | expect { Mail::MessageIdsElement.new(msg_id_text) }.to raise_error(Mail::Field::ParseError)
25 | end
26 |
27 | it "should respond to message_ids" do
28 | msg_id_text = '<1234@test.lindsaar.net> <1234@test.lindsaar.net>'
29 | msg_ids = Mail::MessageIdsElement.new(msg_id_text)
30 | expect(msg_ids.message_ids).to eq ['1234@test.lindsaar.net', '1234@test.lindsaar.net']
31 | end
32 |
33 | it "should respond to message_id" do
34 | msg_id_text = '<1234@test.lindsaar.net>'
35 | msg_ids = Mail::MessageIdsElement.new(msg_id_text)
36 | expect(msg_ids.message_id).to eq '1234@test.lindsaar.net'
37 | end
38 |
39 | it "should not fail to parse a message id with dots in it" do
40 | text = "<4afb664ca3078_48dc..fdbe32b865532b@ax-desktop.mail>"
41 | m = Mail::MessageIdsElement.new(text)
42 | expect(m.message_id).to eq "4afb664ca3078_48dc..fdbe32b865532b@ax-desktop.mail"
43 | end
44 |
45 | end
46 |
--------------------------------------------------------------------------------
/spec/mail/elements/phrase_list_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'spec_helper'
4 |
5 | RSpec.describe Mail::PhraseList do
6 |
7 | describe "parsing" do
8 | it "should parse a phrase list" do
9 | parse_text = '"Mikel Lindsaar", "Mikel", you, somewhere'
10 | expect { Mail::PhraseList.new(parse_text) }.not_to raise_error
11 | end
12 |
13 | it "treats nil as an empty list" do
14 | list = Mail::PhraseList.new(nil)
15 | expect(list.phrases).to eq []
16 | end
17 |
18 | it "should not raise an error if the input is useless" do
19 | parse_text = '""""""""""""""""'
20 | expect(Mail::PhraseList.new(parse_text).phrases).to eq [parse_text[1...-1]]
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/spec/mail/elements/received_element_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'spec_helper'
3 |
4 | RSpec.describe Mail::ReceivedElement do
5 |
6 | it "should raise an error if the input is nil" do
7 | received = Mail::ReceivedElement.new(nil)
8 | expect(received.info).to be_nil
9 | expect(received.date_time).to be_nil
10 | end
11 |
12 | it "should raise an error if the input is useless" do
13 | received_text = '""""""""""""""""'
14 | expect { Mail::ReceivedElement.new(received_text) }.to raise_error(Mail::Field::ParseError)
15 | end
16 |
17 | it "should give back the date time" do
18 | received_text = 'from localhost (localhost [127.0.0.1]) by xxx.xxxxx.com (Postfix) with ESMTP id 50FD3A96F for <xxxx@xxxx.com>; Tue, 10 May 2005 17:26:50 +0000 (GMT)'
19 | date_text = '10 May 2005 17:26:50 +0000 (GMT)'
20 | rec = Mail::ReceivedElement.new(received_text)
21 | expect(rec.date_time).to eq ::DateTime.parse(date_text)
22 | end
23 |
24 | it "should give back the info" do
25 | received_text = 'from localhost (localhost [127.0.0.1]) by xxx.xxxxx.com (Postfix) with ESMTP id 50FD3A96F for <xxxx@xxxx.com>; Tue, 10 May 2005 17:26:50 +0000 (GMT)'
26 | info_text = 'from localhost (localhost [127.0.0.1]) by xxx.xxxxx.com (Postfix) with ESMTP id 50FD3A96F for <xxxx@xxxx.com>'
27 | rec = Mail::ReceivedElement.new(received_text)
28 | expect(rec.info).to eq info_text
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/spec/mail/encodings/base64_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'spec_helper'
3 |
4 | RSpec.describe Mail::Encodings::Base64 do
5 |
6 | it "should encode base 64 from text" do
7 | result = "VGhpcyBpcyBhIHRlc3Q=\r\n"
8 | expect(Mail::Encodings::Base64.encode('This is a test')).to eq result
9 | end
10 |
11 | it "should decode base 64 text" do
12 | result = 'This is a test'
13 | expect(Mail::Encodings::Base64.decode("VGhpcyBpcyBhIHRlc3Q=\n")).to eq result
14 | end
15 |
16 | it "should encode base 64 from binary" do
17 | result = "AAAAAA==\r\n"
18 | expect(Mail::Encodings::Base64.encode("\000\000\000\000")).to eq result
19 | end
20 |
21 | it "should decode base 64 text" do
22 | result = "\000\000\000\000"
23 | expect(Mail::Encodings::Base64.decode("AAAAAA==\n")).to eq result
24 | end
25 |
26 | end
27 |
--------------------------------------------------------------------------------
/spec/mail/encodings/transfer_encoding_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'spec_helper'
3 |
4 | RSpec.describe Mail::Encodings::TransferEncoding do
5 | it "accepts blank message_encoding" do
6 | expect(described_class.negotiate('', '7bit', '')).to eq Mail::Encodings::SevenBit
7 | expect(described_class.negotiate('', '8bit', '')).to eq Mail::Encodings::EightBit
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/spec/mail/encodings/unix_to_unix_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'spec_helper'
4 |
5 | RSpec.describe Mail::Encodings::UnixToUnix do
6 | def decode(str)
7 | Mail::Encodings::UnixToUnix.decode(str)
8 | end
9 |
10 | def encode(str)
11 | Mail::Encodings::UnixToUnix.encode(str)
12 | end
13 |
14 | it "is registered as uuencode" do
15 | expect(Mail::Encodings.get_encoding('uuencode')).to eq(Mail::Encodings::UnixToUnix)
16 | end
17 |
18 | it "is registered as x-uuencode" do
19 | expect(Mail::Encodings.get_encoding('x-uuencode')).to eq(Mail::Encodings::UnixToUnix)
20 | end
21 |
22 | it "is registered as x-uue" do
23 | expect(Mail::Encodings.get_encoding('x-uue')).to eq(Mail::Encodings::UnixToUnix)
24 | end
25 |
26 | it "can transport itself" do
27 | expect(Mail::Encodings::UnixToUnix.can_transport?(Mail::Encodings::UnixToUnix)).to be_truthy
28 | end
29 |
30 | it "decodes" do
31 | text = strip_heredoc(<<-TEXT)
32 | begin 644 Happy.txt
33 | M2&%P<'D@=&]D87D@9F]R('1O(&)E(&]N92!O9B!P96%C92!A;F0@<V5R96YE
34 | '('1I;64N"@``
35 | `
36 | end
37 | TEXT
38 | expect(decode(text)).to eq "Happy today for to be one of peace and serene time.\n"
39 | end
40 |
41 | it "encodes" do
42 | expect(encode("Happy today")).to eq "+2&%P<'D@=&]D87D`\n"
43 | end
44 |
45 | it "encodes / decodes non-ascii" do
46 | expect(encode("Happy ああr")).to eq "-2&%P<'D@XX&\"XX&\"<@``\n"
47 | expect(decode("-2&%P<'D@XX&\"XX&\"<@``\n")).to eq "Happy ああr".dup.force_encoding("binary")
48 | end
49 |
50 | it "can read itself" do
51 | expect(decode(encode("Happy today"))).to eq "Happy today"
52 | expect(encode(decode("+2&%P<'D@=&]D87D`\n"))).to eq "+2&%P<'D@=&]D87D`\n"
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/spec/mail/field_list_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'spec_helper'
3 |
4 | RSpec.describe Mail::FieldList do
5 | it "should be able to add new fields" do
6 | fl = Mail::FieldList.new
7 | fl << Mail::Field.parse("To: mikel@me.com")
8 | fl << Mail::Field.parse("From: mikel@me.com")
9 | expect(fl.map(&:name)).to eq %w[ From To ]
10 | end
11 |
12 | it "should be able to add new fields in the right order" do
13 | fl = Mail::FieldList.new
14 | fl << Mail::Field.parse("To: mikel@me.com")
15 | fl << Mail::Field.parse("From: mikel@me.com")
16 | fl << Mail::Field.parse("Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id 6AAEE3B4D23 for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:23 -0500")
17 | fl << Mail::Field.parse("Return-Path: mikel@me.com")
18 | expect(fl.map(&:name)).to eq %w[ Return-Path Received From To ]
19 | end
20 |
21 | it "should add new Received items after the existing ones" do
22 | fl = Mail::FieldList.new
23 | fl << Mail::Field.parse("To: mikel@me.com")
24 | fl << Mail::Field.parse("From: mikel@me.com")
25 | fl << Mail::Field.parse("Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id 6AAEE3B4D23 for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:23 -0500")
26 | fl << Mail::Field.parse("Return-Path: mikel@me.com")
27 | fl << Mail::Field.parse("Received: from 123.xxxx.xxx by xxx.xxxx.xxx with ESMTP id 6AAEE3B4D23 for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:23 -0500")
28 | expect(fl[2].field.value).to eq 'from 123.xxxx.xxx by xxx.xxxx.xxx with ESMTP id 6AAEE3B4D23 for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:23 -0500'
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/spec/mail/fields/address_container_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'spec_helper'
4 |
5 | RSpec.describe 'AddressContainer' do
6 | it "should allow you to append an address to an address field result" do
7 | m = Mail.new("To: mikel@test.lindsaar.net")
8 | expect(m.to).to eq ['mikel@test.lindsaar.net']
9 | m.to << 'bob@test.lindsaar.net'
10 | expect(m.to).to eq ['mikel@test.lindsaar.net', 'bob@test.lindsaar.net']
11 | end
12 |
13 | it "should handle complex addresses correctly" do
14 | m = Mail.new("From: mikel@test.lindsaar.net")
15 | expect(m.from).to eq ['mikel@test.lindsaar.net']
16 | m.from << '"Ada Lindsaar" <ada@test.lindsaar.net>, bob@test.lindsaar.net'
17 | expect(m.from).to eq ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net', 'bob@test.lindsaar.net']
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/spec/mail/fields/comments_field_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'spec_helper'
4 |
5 | RSpec.describe Mail::CommentsField do
6 | #
7 | # comments = "Comments:" unstructured CRLF
8 |
9 | it "should initialize" do
10 | expect { Mail::CommentsField.new("this is a comment") }.not_to raise_error
11 | end
12 |
13 | it "should accept a string with the field name" do
14 | t = Mail::CommentsField.new('this is a comment')
15 | expect(t.name).to eq 'Comments'
16 | expect(t.value).to eq 'this is a comment'
17 | end
18 |
19 |
20 | end
21 |
--------------------------------------------------------------------------------
/spec/mail/fields/common_date_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'spec_helper'
3 |
4 | RSpec.describe Mail::CommonDateField do
5 | describe "encoding and decoding fields" do
6 | it "should allow us to encode an date field" do
7 | field = Mail::DateField.new('12 Aug 2009 00:00:02 GMT')
8 | expect(field.encoded).to eq "Date: Wed, 12 Aug 2009 00:00:02 +0000\r\n"
9 | end
10 |
11 | it "should allow us to encode an resent date field" do
12 | field = Mail::ResentDateField.new('12 Aug 2009 00:00:02 GMT')
13 | expect(field.encoded).to eq "Resent-Date: Wed, 12 Aug 2009 00:00:02 +0000\r\n"
14 | end
15 |
16 | it "should allow us to decode an address field" do
17 | field = Mail::DateField.new('12 Aug 2009 00:00:02 GMT')
18 | expect(field.decoded).to eq "Wed, 12 Aug 2009 00:00:02 +0000"
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/spec/mail/fields/common_message_id_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'spec_helper'
3 |
4 | RSpec.describe Mail::CommonMessageIdField do
5 |
6 | describe "encoding and decoding fields" do
7 |
8 | it "should allow us to encode a message id field" do
9 | field = Mail::MessageIdField.new('<ThisIsANonUniqueMessageId@me.com>')
10 | expect(field.encoded).to eq "Message-ID: <ThisIsANonUniqueMessageId@me.com>\r\n"
11 | end
12 |
13 | it "should allow us to encode a message id field" do
14 | field = Mail::MessageIdField.new('<1234@test.lindsaar.net>')
15 | expect(field.encoded).to eq "Message-ID: <1234@test.lindsaar.net>\r\n"
16 | end
17 |
18 | it "should allow us to encode an in reply to field" do
19 | field = Mail::InReplyToField.new('<1234@test.lindsaar.net>')
20 | expect(field.encoded).to eq "In-Reply-To: <1234@test.lindsaar.net>\r\n"
21 | end
22 |
23 | it "should allow us to decode a message id field" do
24 | field = Mail::MessageIdField.new('<1234@test.lindsaar.net>')
25 | expect(field.decoded).to eq "<1234@test.lindsaar.net>"
26 | end
27 |
28 | end
29 |
30 | end
31 |
--------------------------------------------------------------------------------
/spec/mail/fields/content_description_field_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'spec_helper'
3 |
4 | RSpec.describe Mail::ContentDescriptionField do
5 | # Content-Description Header Field
6 | #
7 | # The ability to associate some descriptive information with a given
8 | # body is often desirable. For example, it may be useful to mark an
9 | # "image" body as "a picture of the Space Shuttle Endeavor." Such text
10 | # may be placed in the Content-Description header field. This header
11 | # field is always optional.
12 | #
13 | # description := "Content-Description" ":" *text
14 | #
15 | # The description is presumed to be given in the US-ASCII character
16 | # set, although the mechanism specified in RFC 2047 may be used for
17 | # non-US-ASCII Content-Description values.
18 | #
19 |
20 | describe "initialization" do
21 |
22 | it "should initialize" do
23 | expect { Mail::ContentDescriptionField.new("This is a description") }.not_to raise_error
24 | end
25 |
26 | it "should accept a string without the field name" do
27 | t = Mail::ContentDescriptionField.new('This is a description')
28 | expect(t.name).to eq 'Content-Description'
29 | expect(t.value).to eq 'This is a description'
30 | end
31 |
32 | end
33 |
34 | end
35 |
--------------------------------------------------------------------------------
/spec/mail/fields/content_location_field_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'spec_helper'
3 |
4 | RSpec.describe Mail::ContentLocationField do
5 |
6 | # Content-Location Header Field
7 | #
8 | describe "initialization" do
9 |
10 | it "should initialize" do
11 | expect { Mail::ContentLocationField.new("Content-Location", "7bit") }.not_to raise_error
12 | end
13 |
14 | it "should accept a string without the field name" do
15 | t = Mail::ContentLocationField.new('photo.jpg')
16 | expect(t.name).to eq 'Content-Location'
17 | expect(t.value).to eq 'photo.jpg'
18 | end
19 |
20 | it "should render an encoded field" do
21 | t = Mail::ContentLocationField.new('photo.jpg')
22 | expect(t.encoded).to eq "Content-Location: photo.jpg\r\n"
23 | end
24 |
25 | it "should render a decoded field" do
26 | t = Mail::ContentLocationField.new('photo.jpg')
27 | expect(t.decoded).to eq 'photo.jpg'
28 | end
29 |
30 | end
31 |
32 | describe "parsing the value" do
33 |
34 | it "should return an encoding string unquoted" do
35 | t = Mail::ContentLocationField.new('"A quoted filename.jpg"')
36 | expect(t.location).to eq 'A quoted filename.jpg'
37 | end
38 |
39 | end
40 |
41 | end
42 |
--------------------------------------------------------------------------------
/spec/mail/fields/envelope_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'spec_helper'
3 |
4 | RSpec.describe Mail::Envelope do
5 | # From RFC4155 The application/mbox Media Type
6 | #
7 | # o Each message in the mbox database MUST be immediately preceded
8 | # by a single separator line, which MUST conform to the following
9 | # syntax:
10 | #
11 | # The exact character sequence of "From";
12 | #
13 | # a single Space character (0x20);
14 | #
15 | # the email address of the message sender (as obtained from the
16 | # message envelope or other authoritative source), conformant
17 | # with the "addr-spec" syntax from RFC 2822;
18 | #
19 | # a single Space character;
20 | #
21 | # a timestamp indicating the UTC date and time when the message
22 | # was originally received, conformant with the syntax of the
23 | # traditional UNIX 'ctime' output sans timezone (note that the
24 | # use of UTC precludes the need for a timezone indicator);
25 | #
26 | # an end-of-line marker.
27 |
28 | it "should initialize" do
29 | expect { Mail::Envelope.new('mikel@test.lindsaar.net Mon May 2 16:07:05 2005') }.not_to raise_error
30 | end
31 |
32 | describe "accessor methods" do
33 | it "should return the address" do
34 | envelope = Mail::Envelope.new("mikel@test.lindsaar.net Mon Aug 17 00:39:21 2009")
35 | expect(envelope.from).to eq "mikel@test.lindsaar.net"
36 | end
37 |
38 | it "should return the date_time" do
39 | envelope = Mail::Envelope.new("mikel@test.lindsaar.net Mon Aug 17 00:39:21 2009")
40 | expect(envelope.date).to eq ::DateTime.parse("Mon Aug 17 00:39:21 2009")
41 | end
42 | end
43 |
44 | end
45 |
--------------------------------------------------------------------------------
/spec/mail/fields/reply_to_field_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'spec_helper'
4 | #
5 | # reply-to = "Reply-To:" address-list CRLF
6 | #
7 |
8 | RSpec.describe Mail::ReplyToField do
9 |
10 | describe "initialization" do
11 |
12 | it "should initialize" do
13 | expect { Mail::ReplyToField.new("Mikel") }.not_to raise_error
14 | end
15 |
16 | it "should accept a string without the field name" do
17 | t = Mail::ReplyToField.new('Mikel Lindsaar <mikel@test.lindsaar.net>, "Bob Smith" <bob@me.com>')
18 | expect(t.name).to eq 'Reply-To'
19 | expect(t.value).to eq 'Mikel Lindsaar <mikel@test.lindsaar.net>, "Bob Smith" <bob@me.com>'
20 | end
21 |
22 | end
23 |
24 | describe "instance methods" do
25 | it "should return an address" do
26 | t = Mail::ReplyToField.new('Mikel Lindsaar <mikel@test.lindsaar.net>')
27 | expect(t.formatted).to eq ['Mikel Lindsaar <mikel@test.lindsaar.net>']
28 | end
29 |
30 | it "should return two addresses" do
31 | t = Mail::ReplyToField.new('Mikel Lindsaar <mikel@test.lindsaar.net>, Ada Lindsaar <ada@test.lindsaar.net>')
32 | expect(t.formatted.first).to eq 'Mikel Lindsaar <mikel@test.lindsaar.net>'
33 | expect(t.addresses.last).to eq 'ada@test.lindsaar.net'
34 | end
35 |
36 | it "should return one address and a group" do
37 | t = Mail::ReplyToField.new('sam@me.com, my_group: mikel@me.com, bob@you.com;')
38 | expect(t.addresses[0]).to eq 'sam@me.com'
39 | expect(t.addresses[1]).to eq 'mikel@me.com'
40 | expect(t.addresses[2]).to eq 'bob@you.com'
41 | end
42 |
43 | it "should return the formatted line on to_s" do
44 | t = Mail::ReplyToField.new('sam@me.com, my_group: mikel@me.com, bob@you.com;')
45 | expect(t.value).to eq 'sam@me.com, my_group: mikel@me.com, bob@you.com;'
46 | end
47 |
48 | it "should return the encoded line" do
49 | t = Mail::ReplyToField.new('sam@me.com, my_group: mikel@me.com, bob@you.com;')
50 | expect(t.encoded).to eq "Reply-To: sam@me.com, \r\n\smy_group: mikel@me.com, \r\n\sbob@you.com;\r\n"
51 | end
52 |
53 | end
54 |
55 |
56 | end
57 |
--------------------------------------------------------------------------------
/spec/mail/fields/resent_cc_field_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'spec_helper'
4 | #
5 | # resent-cc = "Resent-Cc:" address-list CRLF
6 |
7 | RSpec.describe Mail::ResentCcField do
8 |
9 | describe "initialization" do
10 |
11 | it "should initialize" do
12 | expect { Mail::ResentCcField.new("Mikel") }.not_to raise_error
13 | end
14 |
15 | it "should accept a string without the field name" do
16 | t = Mail::ResentCcField.new('Mikel Lindsaar <mikel@test.lindsaar.net>, "Bob Smith" <bob@me.com>')
17 | expect(t.name).to eq 'Resent-Cc'
18 | expect(t.value).to eq 'Mikel Lindsaar <mikel@test.lindsaar.net>, "Bob Smith" <bob@me.com>'
19 | end
20 |
21 | end
22 |
23 | describe "instance methods" do
24 | it "should return an address" do
25 | t = Mail::ResentCcField.new('Mikel Lindsaar <mikel@test.lindsaar.net>')
26 | expect(t.formatted).to eq ['Mikel Lindsaar <mikel@test.lindsaar.net>']
27 | end
28 |
29 | it "should return two addresses" do
30 | t = Mail::ResentCcField.new('Mikel Lindsaar <mikel@test.lindsaar.net>, Ada Lindsaar <ada@test.lindsaar.net>')
31 | expect(t.formatted.first).to eq 'Mikel Lindsaar <mikel@test.lindsaar.net>'
32 | expect(t.addresses.last).to eq 'ada@test.lindsaar.net'
33 | end
34 |
35 | it "should return one address and a group" do
36 | t = Mail::ResentCcField.new('sam@me.com, my_group: mikel@me.com, bob@you.com;')
37 | expect(t.addresses[0]).to eq 'sam@me.com'
38 | expect(t.addresses[1]).to eq 'mikel@me.com'
39 | expect(t.addresses[2]).to eq 'bob@you.com'
40 | end
41 |
42 | it "should return the formatted line on to_s" do
43 | t = Mail::ResentCcField.new('sam@me.com, my_group: mikel@me.com, bob@you.com;')
44 | expect(t.value).to eq 'sam@me.com, my_group: mikel@me.com, bob@you.com;'
45 | end
46 |
47 | it "should return the encoded line" do
48 | t = Mail::ResentCcField.new('sam@me.com, my_group: mikel@me.com, bob@you.com;')
49 | expect(t.encoded).to eq "Resent-Cc: sam@me.com, \r\n\smy_group: mikel@me.com, \r\n\sbob@you.com;\r\n"
50 | end
51 |
52 | end
53 |
54 |
55 | end
56 |
--------------------------------------------------------------------------------
/spec/mail/fields/resent_date_field_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'spec_helper'
4 |
5 | RSpec.describe Mail::ResentDateField do
6 | it "should initialize" do
7 | expect { Mail::ResentDateField.new("12 Aug 2009 00:00:02 GMT") }.not_to raise_error
8 | end
9 |
10 | it "should be able to tell the time" do
11 | expect(Mail::ResentDateField.new("12 Aug 2009 00:00:02 GMT").date_time.class).to eq DateTime
12 | end
13 |
14 | it "should accept a string without the field name" do
15 | t = Mail::ResentDateField.new('12 Aug 2009 00:00:02 GMT')
16 | expect(t.name).to eq 'Resent-Date'
17 | expect(t.value).to eq 'Wed, 12 Aug 2009 00:00:02 +0000'
18 | expect(t.date_time).to eq ::DateTime.parse('12 Aug 2009 00:00:02 GMT')
19 | end
20 |
21 | it "should give today's date if no date is specified" do
22 | now = DateTime.now
23 | expect(DateTime).to receive(:now).at_least(:once).and_return(now)
24 | t = Mail::ResentDateField.new
25 | expect(t.name).to eq 'Resent-Date'
26 | expect(t.date_time).to eq ::DateTime.parse(now.to_s)
27 | end
28 |
29 | end
30 |
--------------------------------------------------------------------------------
/spec/mail/fields/resent_message_id_field_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'spec_helper'
4 |
5 | RSpec.describe Mail::ResentMessageIdField do
6 |
7 | it "should initialize" do
8 | expect { Mail::ResentMessageIdField.new("<1234@test.lindsaar.net>") }.not_to raise_error
9 | end
10 |
11 | it "should accept a string without the field name" do
12 | t = Mail::ResentMessageIdField.new('<1234@test.lindsaar.net>')
13 | expect(t.name).to eq 'Resent-Message-ID'
14 | expect(t.value).to eq '<1234@test.lindsaar.net>'
15 | expect(t.message_id).to eq '1234@test.lindsaar.net'
16 | end
17 |
18 | it "should output lines shorter than 998 chars" do
19 | k = Mail::ResentMessageIdField.new('<Kohciuku@apholoVu.com> <foovohPu@Thegahsh.com> <UuseZeow@oocieBie.com> <UchaeKoo@eeJoukie.com> <ieKahque@ieGoochu.com> <aZaXaeva@ungaiGai.com> <sheiraiK@ookaiSha.com> <weijooPi@ahfuRaeh.com> <FiruJeur@weiphohP.com> <cuadoiQu@aiZuuqua.com> <YohGieVe@Reacepae.com> <Ieyechum@ephooGho.com> <uGhievoo@vusaeciM.com> <ouhieTha@leizaeTi.com> <ohgohGhu@jieNgooh.com> <ahNookah@oChiecoo.com> <taeWieTu@iuwiLooZ.com> <Kohraiji@AizohGoa.com> <hiQuaegh@eeluThii.com> <Uunaesoh@UogheeCh.com> <JeQuahMa@Thahchoh.com> <aaxohJoh@ahfaeCho.com> <Pahneehu@eehooChi.com> <angeoKah@Wahsaeme.com> <ietovoaV@muewaeZi.com> <aebiuZur@oteeYaiF.com> <pheiXahw@Muquahba.com> <aNgiaPha@bohliNge.com> <Eikawohf@IevaiQuu.com> <gihaeduZ@Raighiey.com> <Theequoh@hoamaeSa.com> <VeiVooyi@aimuQuoo.com> <ahGoocie@BohpheVi.com> <roivahPa@uPhoghai.com> <gioZohli@Gaochoow.com> <eireLair@phaevieR.com> <TahthaeC@oolaiBei.com> <phuYeika@leiKauPh.com> <BieYenoh@Xaebaalo.com> <xohvaeWa@ahghaeRe.com> <thoQuohV@Ubooheay.com> <pheeWohV@feicaeNg.com>')
20 | lines = k.encoded.split("\r\n\s")
21 | lines.each { |line| expect(line.length).to be < 998 }
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/spec/mail/fields/resent_sender_field_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'spec_helper'
4 |
5 | # resent-sender = "Resent-Sender:" mailbox CRLF
6 | RSpec.describe Mail::ResentSenderField do
7 | let :field do
8 | Mail::ResentSenderField.new('Mikel Lindsaar <mikel@test.lindsaar.net>')
9 | end
10 |
11 | describe "initialization" do
12 |
13 | it "should initialize" do
14 | expect { Mail::ResentSenderField.new("Mikel") }.not_to raise_error
15 | end
16 |
17 | it "should accept a string without the field name" do
18 | t = Mail::ResentSenderField.new('Mikel Lindsaar <mikel@test.lindsaar.net>, "Bob Smith" <bob@me.com>')
19 | expect(t.name).to eq 'Resent-Sender'
20 | expect(t.value).to eq 'Mikel Lindsaar <mikel@test.lindsaar.net>, "Bob Smith" <bob@me.com>'
21 | end
22 |
23 | end
24 |
25 | it "formats the sender" do
26 | expect(field.formatted).to eq ['Mikel Lindsaar <mikel@test.lindsaar.net>']
27 | end
28 |
29 | it "parses a single sender address" do
30 | expect(field.address).to eq 'mikel@test.lindsaar.net'
31 | end
32 |
33 | it "returns the field value" do
34 | expect(field.value).to eq 'Mikel Lindsaar <mikel@test.lindsaar.net>'
35 | end
36 |
37 | it "encodes a header line" do
38 | expect(field.encoded).to eq "Resent-Sender: Mikel Lindsaar <mikel@test.lindsaar.net>\r\n"
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/spec/mail/fields/return_path_field_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require 'spec_helper'
3 |
4 | RSpec.describe Mail::ReturnPathField do
5 | it "should allow you to specify a field" do
6 | rp = Mail::ReturnPathField.new('mikel@test.lindsaar.net')
7 | expect(rp.address).to eq 'mikel@test.lindsaar.net'
8 | end
9 |
10 | it "should encode the addr_spec in <>" do
11 | rp = Mail::ReturnPathField.new('mikel@test.lindsaar.net')
12 | expect(rp.encoded).to eq "Return-Path: <mikel@test.lindsaar.net>\r\n"
13 | end
14 |
15 | it "should accept <>" do
16 | rp = Mail::ReturnPathField.new('<>')
17 | expect(rp.encoded).to eq "Return-Path: <>\r\n"
18 | end
19 |
20 | it "should set the return path" do
21 | mail = Mail.new do
22 | to "to@someemail.com"
23 | from "from@someemail.com"
24 | subject "Can't set the return-path"
25 | return_path "bounce@someemail.com"
26 | message_id "<1234@someemail.com>"
27 | body "body"
28 | end
29 | expect(mail.return_path).to eq "bounce@someemail.com"
30 | end
31 |
32 | it "should set the return path" do
33 | mail = Mail.new do
34 | to "to@someemail.com"
35 | from "from@someemail.com"
36 | subject "Can't set the return-path"
37 | return_path "bounce@someemail.com"
38 | message_id "<1234@someemail.com>"
39 | body "body"
40 | end
41 | encoded_mail = Mail.new(mail.encoded)
42 | expect(encoded_mail.return_path).to eq "bounce@someemail.com"
43 | end
44 |
45 | it "should wrap the return path addr_spec in <>" do
46 | mail = Mail.new do
47 | to "to@someemail.com"
48 | from "from@someemail.com"
49 | subject "Can't set the return-path"
50 | return_path "bounce@someemail.com"
51 | message_id "<1234@someemail.com>"
52 | body "body"
53 | end
54 | expect(mail.encoded).to match(/<bounce@someemail\.com>/)
55 | end
56 |
57 |
58 | end
59 |
--------------------------------------------------------------------------------
/spec/mail/fields/sender_field_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'spec_helper'
4 |
5 | # sender = "Sender:" mailbox CRLF
6 | RSpec.describe Mail::SenderField do
7 | let :field do
8 | Mail::SenderField.new('Mikel Lindsaar <mikel@test.lindsaar.net>')
9 | end
10 |
11 | describe "initialization" do
12 | it "should initialize" do
13 | expect { Mail::SenderField.new("Mikel") }.not_to raise_error
14 | end
15 |
16 | it "should accept a string without the field name" do
17 | t = Mail::SenderField.new('Mikel Lindsaar <mikel@test.lindsaar.net>')
18 | expect(t.name).to eq 'Sender'
19 | expect(t.value).to eq 'Mikel Lindsaar <mikel@test.lindsaar.net>'
20 | end
21 |
22 | it "should reject headers with multiple mailboxes" do
23 | pending 'Sender accepts an address list now, but should only accept a single address'
24 | expect {
25 | Mail::SenderField.new('Mikel Lindsaar <mikel@test.lindsaar.net>, "Bob Smith" <bob@me.com>')
26 | }.to raise_error(Mail::Field::ParseError)
27 | end
28 | end
29 |
30 | it "formats the sender" do
31 | expect(field.formatted).to eq ['Mikel Lindsaar <mikel@test.lindsaar.net>']
32 | end
33 |
34 | it "parses a single sender address" do
35 | expect(field.address).to eq 'mikel@test.lindsaar.net'
36 | end
37 |
38 | it "returns the field value" do
39 | expect(field.value).to eq 'Mikel Lindsaar <mikel@test.lindsaar.net>'
40 | end
41 |
42 | it "encodes a header line" do
43 | expect(field.encoded).to eq "Sender: Mikel Lindsaar <mikel@test.lindsaar.net>\r\n"
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/spec/mail/fields/structured_field_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'spec_helper'
4 |
5 | RSpec.describe Mail::StructuredField do
6 |
7 | describe "initialization" do
8 |
9 | it "should be instantiated" do
10 | expect {Mail::StructuredField.new("From", "bob@me.com")}.not_to raise_error
11 | end
12 |
13 | end
14 |
15 | describe "manipulation" do
16 |
17 | before(:each) do
18 | @field = Mail::StructuredField.new("From", "bob@me.com")
19 | end
20 |
21 | it "should allow us to set a text value at initialization" do
22 | expect{Mail::StructuredField.new("From", "bob@me.com")}.not_to raise_error
23 | end
24 |
25 | it "should provide access to the text of the field once set" do
26 | expect(@field.value).to eq "bob@me.com"
27 | end
28 |
29 | it "should provide a means to change the value" do
30 | @field.value = "bob@you.com"
31 | expect(@field.value).to eq "bob@you.com"
32 | end
33 | end
34 |
35 | describe "displaying encoded field and decoded value" do
36 |
37 | before(:each) do
38 | @field = Mail::FromField.new("bob@me.com")
39 | end
40 |
41 | it "should provide a to_s function that returns the decoded string" do
42 | expect(@field.to_s).to eq "bob@me.com"
43 | end
44 |
45 | it "should return '' on to_s if there is no value" do
46 | @field.value = nil
47 | expect(@field.encoded).to eq ''
48 | end
49 |
50 | it "should give an encoded value ready to insert into an email" do
51 | expect(@field.encoded).to eq "From: bob@me.com\r\n"
52 | end
53 |
54 | it "should return an empty string on encoded if it has no value" do
55 | @field.value = nil
56 | expect(@field.encoded).to eq ''
57 | end
58 |
59 | it "should return the field name and value in proper format when called to_s" do
60 | expect(@field.encoded).to eq "From: bob@me.com\r\n"
61 | end
62 | end
63 | end
64 |
--------------------------------------------------------------------------------
/spec/mail/multibyte_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'spec_helper'
4 | require 'mail/multibyte/chars'
5 |
6 | RSpec.describe Mail::Multibyte::Chars do
7 | it "should upcase" do
8 | chars = described_class.new('Laurent, où sont les tests ?')
9 | expect(chars.upcase).to eq("LAURENT, OÙ SONT LES TESTS ?")
10 | end
11 |
12 | it "should downcase" do
13 | chars = described_class.new('VĚDA A VÝZKUM')
14 | expect(chars.downcase).to eq("věda a výzkum")
15 | end
16 |
17 | if 'string'.respond_to?(:force_encoding)
18 | it "doesn't mutate input string encoding" do
19 | s = 'ascii'.dup.force_encoding(Encoding::US_ASCII)
20 | described_class.new(s)
21 | expect(s.encoding).to eq(Encoding::US_ASCII)
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/spec/mail/round_tripping_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'spec_helper'
4 |
5 | RSpec.describe "Round Tripping" do
6 |
7 | it "should round trip a basic email" do
8 | mail = Mail.new('Subject: FooBar')
9 | mail.body "This is Text"
10 | parsed_mail = Mail.new(mail.to_s)
11 | expect(parsed_mail.subject.to_s).to eq "FooBar"
12 | expect(parsed_mail.body.to_s).to eq "This is Text"
13 | end
14 |
15 | it "should round trip a html multipart email" do
16 | mail = Mail.new('Subject: FooBar')
17 | mail.text_part = Mail::Part.new do
18 | body "This is Text"
19 | end
20 | mail.html_part = Mail::Part.new do
21 | content_type "text/html; charset=US-ASCII"
22 | body "<b>This is HTML</b>"
23 | end
24 | parsed_mail = Mail.new(mail.to_s)
25 | expect(parsed_mail.mime_type).to eq 'multipart/alternative'
26 | expect(parsed_mail.boundary).to eq mail.boundary
27 | expect(parsed_mail.parts.length).to eq 2
28 | expect(parsed_mail.parts[0].body.to_s).to eq "This is Text"
29 | expect(parsed_mail.parts[1].body.to_s).to eq "<b>This is HTML</b>"
30 | end
31 |
32 | it "should round trip an email" do
33 | initial = Mail.new do
34 | to "mikel@test.lindsaar.net"
35 | subject "testing round tripping"
36 | body "Really testing round tripping."
37 | from "system@test.lindsaar.net"
38 | cc "nobody@test.lindsaar.net"
39 | bcc "bob@test.lindsaar.net"
40 | date Time.local(2009, 11, 6)
41 | add_file :filename => "foo.txt", :content => "I have \ntwo lines\n\n"
42 | end
43 | expect(Mail.new(initial.encoded).encoded).to eq initial.encoded
44 | end
45 |
46 | it "preserves text attachment newlines" do
47 | body = "I have \r\ntwo lines\n\r"
48 | initial = Mail.new
49 | initial.add_file :filename => "foo.txt", :content => body
50 | expect(Mail.new(initial.encoded).attachments.first.decoded).to eq ::Mail::Utilities.binary_unsafe_to_lf(body)
51 | end
52 | end
53 |
--------------------------------------------------------------------------------
/spec/mail/yaml_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | require 'spec_helper'
4 |
5 | RSpec.describe Mail::YAML do
6 |
7 | describe "#load" do
8 |
9 | it 'loads YAML' do
10 | expect(Mail::YAML.load('{}')).to eq({})
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/matchers/break_down_to.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module CustomMatchers
3 | class BreakDownTo
4 | def initialize(expected)
5 | @expected = expected
6 | end
7 |
8 | def matches?(target)
9 | @target = target
10 | @failed = false
11 | @expected.each_pair do |k,v|
12 | @failed = k unless @target.send(k) == @expected[k]
13 | end
14 | !@failed
15 | end
16 |
17 | def failure_message
18 | "expected #{@failed} to be |#{@expected[@failed]}| " +
19 | "but was |#{@target.send(@failed)}|"
20 | end
21 |
22 | def failure_message_when_negated
23 | "expected #{@failed} not to be |#{@expected[@failed]}| " +
24 | "and was |#{@target.send(@failed)}|"
25 | end
26 |
27 | end
28 |
29 | # Actual matcher that is exposed.
30 | def break_down_to(expected)
31 | BreakDownTo.new(expected)
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/tools/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'rubygems'
3 | require 'bundler/setup'
4 |
5 | begin
6 | require 'byebug'
7 | rescue LoadError
8 | end
9 |
10 | require 'mail'
11 |
12 | require 'irb'
13 | require 'irb/completion'
14 | IRB.start
15 |
--------------------------------------------------------------------------------