Mail adalah perpustakaan internet untuk Ruby yang dirancang untuk menangani pembuatan email, penguraian dan pengiriman rubyesque yang sederhana.
Tujuan perpustakaan ini adalah untuk memberikan satu titik akses untuk menangani semua fungsi email, termasuk mengirim dan menerima email. Semua Tindakan Jenis Jaringan dilakukan melalui metode proxy ke NET :: SMTP, NET :: POP3 dll.
Dibangun dari pengalaman saya dengan Tmail, ini dirancang untuk menjadi implementasi Ruby murni yang membuat menghasilkan, mengirim, dan mem -parsing email menjadi tidak peduli.
Ini juga dirancang dari bawah ke atas untuk bekerja dengan versi Ruby yang lebih modern. Rubi modern menangani pengkodean teks jauh lebih luar biasa dari sebelumnya sehingga fitur -fitur ini telah dimanfaatkan sepenuhnya di perpustakaan ini yang memungkinkan surat untuk menangani lebih banyak pesan lebih bersih daripada tmail.
Akhirnya, Mail telah dirancang dengan sistem berorientasi objek yang sangat sederhana yang benar -benar membuka pesan email yang Anda puratkan, jika Anda tahu apa yang Anda lakukan, Anda dapat mengutak -atik setiap bit terakhir dari email Anda secara langsung.
Ya, kamu! Surat digunakan dalam aplikasi yang tak terhitung jumlahnya oleh orang -orang di seluruh dunia. Ini, seperti semua perangkat lunak open source, tenaga kerja cinta yang ditanggung dari waktu luang kami. Jika Anda ingin mengucapkan terima kasih, silakan gali dan berkontribusi bersama kami! Triage dan perbaiki masalah gitub, tingkatkan dokumentasi kami, tambahkan fitur baru - untuk Anda! Terima kasih telah melakukan pitching.
Surat diuji terhadap:
Saat versi baru Ruby dirilis, surat akan kompatibel dengan dukungan untuk "pratinjau" dan semua "pemeliharaan normal", "pemeliharaan keamanan" dan dua versi "akhir kehidupan" terbaru yang terdaftar di halaman Cabang Pemeliharaan Ruby. Permintaan tarik untuk membantu dalam menambahkan dukungan untuk rilis pratinjau baru lebih dari disambut.
Setiap komitmen surat diuji dengan tindakan github pada semua versi Ruby yang didukung.
Jika Anda ingin membahas surat dengan orang -orang yang berpikiran sama, silakan berlangganan grup Google.
Mail adalah RFC5322 dan RFC6532 sekarang, yaitu, dapat mengurai email AS-ASSAS dan UTF-8 dan menghasilkan email AS-ASSASI. Ada beberapa sintaks email yang sudah usang yang akan memiliki masalah dengan, tetapi juga cukup kuat, artinya, jika ia menemukan sesuatu yang tidak dipahaminya tidak akan macet, sebaliknya, itu akan melewatkan masalah dan tetap mengurai. Dalam kasus header yang tidak dipahami, itu akan menginisialisasi header sebagai bidang opsional yang tidak terstruktur dan terus parsing.
Ini berarti Mail tidak akan (pernah) mengacaukan data Anda (saya pikir).
Anda juga dapat membuat email MIME. Ada metode pembantu untuk membuat email multipart/alternatif untuk teks/polos dan teks/html (pasangan yang paling umum) dan Anda dapat secara manual membuat jenis email MIME lainnya.
Di sebelah Todo:
Pada dasarnya ... kami melakukan BDD melalui surat. Tidak ada metode yang ditulis dalam surat tanpa spek yang sesuai atau meliput. Kami berharap sebagai cakupan minimum 100% yang diukur oleh RCOV. Meskipun ini tidak sempurna dengan ukuran apa pun, itu cukup bagus. Selain itu, semua tes fungsional dari tmail harus lulus sebelum permata dirilis.
Ini juga berarti Anda dapat yakin surat akan berperilaku dengan benar.
Anda dapat menjalankan tes secara lokal dengan menjalankan bundle exec rspec
.
Anda dapat menjalankan tes pada semua versi Ruby yang didukung dengan menggunakan ACT.
Tidak ada pemindahan API dalam satu poin rilis. Semua pemindahan yang akan ditinggalkan dengan peringatan untuk setidaknya satu rilis poin kecil sebelum dihapus.
Juga, semua metode pribadi atau terlindungi untuk dinyatakan seperti itu - meskipun ini masih I/p.
Instalasi cukup sederhana, saya host surat di rubygems, jadi Anda bisa melakukannya:
# gem install mail
Jika Anda tidak tahu, menangani pengkodean dalam email tidak semudah yang Anda harapkan.
Saya telah mencoba menyederhanakannya beberapa:
Semua objek yang dapat membuat email, memiliki metode #encoded
. Dikodekan akan mengembalikan objek sebagai string lengkap yang siap untuk mengirim dalam sistem surat, yaitu, itu akan mencakup bidang header dan nilai dan CRLF di akhir dan dibungkus sesuai kebutuhan.
Semua objek yang dapat membuat email, memiliki metode #decoded
. Decoded akan mengembalikan "nilai" objek hanya sebagai string. Ini berarti tidak akan termasuk bidang header (seperti 'untuk:' atau 'subjek:').
Secara default, memanggil #to_s
pada objek kontainer akan memanggil metode yang dikodekan, sementara #to_s
pada objek lapangan akan memanggil metode yang diterjemahkan. Jadi menelepon #to_s
pada objek email akan mengembalikan surat, semua yang dikodekan siap untuk dikirim, sambil menelepon #to_s
di bidang dari bidang atau badan akan mengembalikan nilai yang diterjemahkan dari objek. Objek header surat dianggap sebagai wadah. Jika Anda ragu, hubungi #encoded
, atau #decoded
secara eksplisit, ini lebih aman jika Anda tidak yakin.
Bidang terstruktur yang memiliki nilai parameter yang dapat dikodekan (misalnya tipe konten) akan memberikan nilai parameter yang diterjemahkan ketika Anda memanggil nama parameter sebagai metode terhadap objek.
Bidang terstruktur yang memiliki nilai parameter yang dapat dikodekan (misalnya tipe konten) akan memberikan nilai parameter yang dikodekan ketika Anda memanggil nama parameter melalui object.parameters['<parameter_name>']
Panggilan metode.
Tolong lakukan! Kontribusi mudah dalam surat. Harap baca dokumen Contributing.md untuk info lebih lanjut.
Semua fungsi surat utama harus dapat terjadi dari modul surat. Jadi, Anda harus hanya dapat require 'mail'
untuk memulai.
mail
didokumentasikan dengan cukup baik dalam kode Ruby -nya. Anda dapat mencarinya misalnya di rubydoc.info.
mail = Mail . new do
from '[email protected]'
to '[email protected]'
subject 'This is a test email'
body File . read ( 'body.txt' )
end
mail . to_s #=> "From: [email protected]: you@...
mail = Mail . new do
body File . read ( 'body.txt' )
end
mail [ 'from' ] = '[email protected]'
mail [ :to ] = '[email protected]'
mail . subject = 'This is a test email'
mail . header [ 'X-Custom-Header' ] = 'custom value'
mail . to_s #=> "From: [email protected]: you@...
mail = Mail . new do
to '[email protected]'
body 'Some simple body'
end
mail . to_s =~ /Message - ID: <[ d w _]+@.+.mail/ #=> 27
Surat akan secara otomatis menambahkan bidang pesan-ID jika hilang dan memberikannya pesan yang unik dan acak di sepanjang baris:
mail = Mail . new do
to '[email protected]'
message_id '<[email protected]>'
body 'Some simple body'
end
mail . to_s =~ /Message - ID: <[email protected]>/ #=> 27
Surat akan mengambil pesan_id yang Anda tetapkan untuk mempercayai bahwa Anda tahu apa yang Anda lakukan.
Mail Default ke pengiriman melalui SMTP ke port host lokal 25. Jika Anda memiliki daemon sendmail atau postfix yang berjalan di port ini, mengirim email semudah:
Mail . deliver do
from '[email protected]'
to '[email protected]'
subject 'Here is the image you wanted'
body File . read ( 'body.txt' )
add_file '/full/path/to/somefile.png'
end
atau
mail = Mail . new do
from '[email protected]'
to '[email protected]'
subject 'Here is the image you wanted'
body File . read ( 'body.txt' )
add_file :filename => 'somefile.png' , :content => File . read ( '/somefile.png' )
end
mail . deliver!
Mengirim melalui sendmail dapat dilakukan seperti itu:
mail = Mail . new do
from '[email protected]'
to '[email protected]'
subject 'Here is the image you wanted'
body File . read ( 'body.txt' )
add_file :filename => 'somefile.png' , :content => File . read ( '/somefile.png' )
end
mail . delivery_method :sendmail
mail . deliver
Mengirim melalui SMTP (misalnya ke MailCatcher)
Mail . defaults do
delivery_method :smtp , address : "localhost" , port : 1025
end
Exim membutuhkan manajer pengirimannya sendiri, dan dapat digunakan seperti itu:
mail . delivery_method :exim , :location => "/usr/bin/exim"
mail . deliver
Surat dapat "dikirim" ke logfile juga, untuk pengembangan dan pengujian:
# Delivers by logging the encoded message to $stdout
mail . delivery_method :logger
# Delivers to an existing logger at :debug severity
mail . delivery_method :logger , logger : other_logger , severity : :debug
Anda dapat mengonfigurasi email untuk menerima email menggunakan retriever_method
di dalam Mail.defaults
:
# e.g. POP3
Mail . defaults do
retriever_method :pop3 , :address => "pop.gmail.com" ,
:port => 995 ,
:user_name => '<username>' ,
:password => '<password>' ,
:enable_ssl => true
end
# IMAP
Mail . defaults do
retriever_method :imap , :address => "imap.mailbox.org" ,
:port => 993 ,
:user_name => '<username>' ,
:password => '<password>' ,
:enable_ssl => true
end
Anda dapat mengakses email yang masuk dalam beberapa cara.
Email terbaru:
Mail . all #=> Returns an array of all emails
Mail . first #=> Returns the first unread email
Mail . last #=> Returns the last unread email
10 email pertama diurutkan berdasarkan tanggal dalam urutan naik:
emails = Mail . find ( :what => :first , :count => 10 , :order => :asc )
emails . length #=> 10
Atau bahkan semua email:
emails = Mail . all
emails . length #=> LOTS!
mail = Mail . read ( '/path/to/message.eml' )
mail . envelope_from #=> '[email protected]'
mail . from . addresses #=> ['[email protected]', '[email protected]']
mail . sender . address #=> '[email protected]'
mail . to #=> '[email protected]'
mail . cc #=> '[email protected]'
mail . subject #=> "This is the subject"
mail . date . to_s #=> '21 Nov 1997 09:55:06 -0600'
mail . message_id #=> '<[email protected]>'
mail . decoded #=> 'This is the body of the email...
Lebih banyak metode yang tersedia.
mail = Mail . read ( 'multipart_email' )
mail . multipart? #=> true
mail . parts . length #=> 2
mail . body . preamble #=> "Text before the first part"
mail . body . epilogue #=> "Text after the last part"
mail . parts . map { | p | p . content_type } #=> ['text/plain', 'application/pdf']
mail . parts . map { | p | p . class } #=> [Mail::Message, Mail::Message]
mail . parts [ 0 ] . content_type_parameters #=> {'charset' => 'ISO-8859-1'}
mail . parts [ 1 ] . content_type_parameters #=> {'name' => 'my.pdf'}
Surat menghasilkan pohon bagian. Setiap pesan memiliki banyak atau tidak ada bagian. Setiap bagian adalah pesan lain yang dapat memiliki banyak atau tidak ada bagian.
Pesan hanya akan memiliki bagian jika merupakan jenis konten multipart/campuran atau multipart/terkait dan memiliki batas yang ditentukan.
mail . attachments . each do | attachment |
# Attachments is an AttachmentsList object containing a
# number of Part objects
if ( attachment . content_type . start_with? ( 'image/' ) )
# extracting images for example...
filename = attachment . filename
begin
File . open ( images_dir + filename , "w+b" , 0644 ) { | f | f . write attachment . decoded }
rescue => e
puts "Unable to save data for #{ filename } because #{ e . message } "
end
end
end
Surat membuat beberapa asumsi dasar dan membuat melakukan hal umum sesederhana mungkin .... (bertanya banyak dari perpustakaan surat)
mail = Mail . deliver do
part :content_type => "multipart/mixed" do | p1 |
p1 . part :content_type => "multipart/related" do | p2 |
p2 . part :content_type => "multipart/alternative" ,
:content_disposition => "inline" do | p3 |
p3 . part :content_type => "text/plain; charset=utf-8" ,
:body => "Here is the attachment you wanted n "
p3 . part :content_type => "text/html; charset=utf-8" ,
:body => "<h1>Funky Title</h1><p>Here is the attachment you wanted</p> n "
end
end
add_file '/path/to/myfile.pdf'
end
from "Mikel Lindsaar <[email protected]>"
to "[email protected]"
subject "First multipart email sent with Mail"
end
Mail kemudian memberikan email di akhir blok dan mengembalikan Objek Mail :: Pesan yang dihasilkan, yang kemudian dapat Anda periksa jika Anda menginginkannya ...
puts mail.to_s #=>
Date: Tue, 26 Apr 2022 20:12:07 +0200
From: Mikel Lindsaar <[email protected]>
To: [email protected]
Message-ID: <[email protected]>
Subject: First multipart email sent with Mail
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="--==_mimepart_626835f733867_10873fdfa3c2ffd494636";
charset=UTF-8
Content-Transfer-Encoding: 7bit
----==_mimepart_626835f733867_10873fdfa3c2ffd494636
Content-Type: multipart/mixed;
boundary="--==_mimepart_626835f73382a_10873fdfa3c2ffd494518";
charset=UTF-8
Content-Transfer-Encoding: 7bit
----==_mimepart_626835f73382a_10873fdfa3c2ffd494518
Content-Type: multipart/related;
boundary="--==_mimepart_626835f7337f5_10873fdfa3c2ffd494438";
charset=UTF-8
Content-Transfer-Encoding: 7bit
----==_mimepart_626835f7337f5_10873fdfa3c2ffd494438
Content-Type: multipart/alternative;
boundary="--==_mimepart_626835f733702_10873fdfa3c2ffd494376";
charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Content-ID: <[email protected]>
----==_mimepart_626835f733702_10873fdfa3c2ffd494376
Content-Type: text/plain;
charset=utf-8
Content-Transfer-Encoding: 7bit
Here is the attachment you wanted
----==_mimepart_626835f733702_10873fdfa3c2ffd494376
Content-Type: text/html;
charset=utf-8
Content-Transfer-Encoding: 7bit
<h1>Funky Title</h1><p>Here is the attachment you wanted</p>
----==_mimepart_626835f733702_10873fdfa3c2ffd494376--
----==_mimepart_626835f7337f5_10873fdfa3c2ffd494438--
----==_mimepart_626835f73382a_10873fdfa3c2ffd494518--
----==_mimepart_626835f733867_10873fdfa3c2ffd494636
Content-Type: text/plain;
charset=UTF-8;
filename=myfile.txt
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename=myfile.txt
Content-ID: <6
[email protected]>
Hallo,
Test
End
----==_mimepart_626835f733867_10873fdfa3c2ffd494636--
Surat menyisipkan pengkodean transfer konten, versi mime, ID konten dan menangani tipe dan batas konten.
Mail mengasumsikan bahwa jika teks Anda dalam tubuh hanya AS-ASCII, bahwa penyandian transfer Anda adalah 7bit dan itu teks/polos. Anda dapat mengesampingkan ini dengan secara eksplisit menyatakannya.
Anda tidak perlu menggunakan blok dengan bagian teks dan bagian HTML, Anda bisa melakukannya dengan deklaratif. Namun, Anda perlu menambahkan mail :: bagian ke email, bukan pesan :: pesan.
mail = Mail . new do
to '[email protected]'
from 'Mikel Lindsaar <[email protected]>'
subject 'First multipart email sent with Mail'
end
text_part = Mail :: Part . new do
body 'This is plain text'
end
html_part = Mail :: Part . new do
content_type 'text/html; charset=UTF-8'
body '<h1>This is HTML</h1>'
end
mail . text_part = text_part
mail . html_part = html_part
Menghasilkan email yang sama seperti yang dilakukan menggunakan formulir blok
@mail = Mail . read ( '/path/to/bounce_message.eml' )
@mail . bounced? #=> true
@mail . final_recipient #=> rfc822;[email protected]
@mail . action #=> failed
@mail . error_status #=> 5.5.0
@mail . diagnostic_code #=> smtp;550 Requested action not taken: mailbox unavailable
@mail . retryable? #=> false
Anda hanya bisa membaca file dari jalur absolut, surat akan mencoba menebak mime_type dan akan menyandikan file di base64 untuk Anda.
@mail = Mail . new
@mail . add_file ( "/path/to/file.jpg" )
@mail . parts . first . attachment? #=> true
@mail . parts . first . content_transfer_encoding . to_s #=> 'base64'
@mail . attachments . first . mime_type #=> 'image/jpg'
@mail . attachments . first . filename #=> 'file.jpg'
@mail . attachments . first . decoded == File . read ( '/path/to/file.jpg' ) #=> true
Atau Anda dapat lulus di file_data dan memberikan nama file, sekali lagi, surat akan mencoba dan menebak mime_type untuk Anda.
@mail = Mail . new
@mail . attachments [ 'myfile.pdf' ] = File . read ( 'path/to/myfile.pdf' )
@mail . parts . first . attachment? #=> true
@mail . attachments . first . mime_type #=> 'application/pdf'
@mail . attachments . first . decoded == File . read ( 'path/to/myfile.pdf' ) #=> true
Anda juga dapat mengesampingkan jenis media Mime yang ditebak jika Anda benar -benar tahu lebih baik daripada Mail (ini jarang dibutuhkan)
@mail = Mail . new
@mail . attachments [ 'myfile.pdf' ] = { :mime_type => 'application/x-pdf' ,
:content => File . read ( 'path/to/myfile.pdf' ) }
@mail . parts . first . mime_type #=> 'application/x-pdf'
Tentu saja ... surat akan pulang ke lampiran juga
@mail = Mail . new do
to '[email protected]'
from 'Mikel Lindsaar <[email protected]>'
subject 'First multipart email sent with Mail'
text_part do
body 'Here is the attachment you wanted'
end
html_part do
content_type 'text/html; charset=UTF-8'
body '<h1>Funky Title</h1><p>Here is the attachment you wanted</p>'
end
add_file '/path/to/myfile.pdf'
end
@round_tripped_mail = Mail . new ( @mail . encoded )
@round_tripped_mail . attachments . length #=> 1
@round_tripped_mail . attachments . first . filename #=> 'myfile.pdf'
Lihat "Menguji dan Mengekstrak Lampiran" di atas untuk detail lebih lanjut.
Jika Mail adalah bagian dari sistem Anda, Anda akan memerlukan cara untuk mengujinya tanpa benar -benar mengirim email, testmailer dapat melakukan ini untuk Anda.
require 'mail'
=> true
Mail . defaults do
delivery_method :test
end
=> #<Mail::Configuration:0x19345a8 @delivery_method=Mail::TestMailer>
Mail :: TestMailer . deliveries
=> [ ]
Mail . deliver do
to '[email protected]'
from '[email protected]'
subject 'testing'
body 'hello'
end
=> #<Mail::Message:0x19284ec ...
Mail :: TestMailer . deliveries . length
=> 1
Mail :: TestMailer . deliveries . first
=> #<Mail::Message:0x19284ec ...
Mail :: TestMailer . deliveries . clear
=> [ ]
Ada juga satu set pencocokan RSPEC yang dicuri/diilhami oleh pencocokan ActionMailer OUSDA (Anda akan ingin mengatur delivery_method
seperti di atas juga):
Mail . defaults do
delivery_method :test # in practice you'd do this in spec_helper.rb
end
RSpec . describe "sending an email" do
include Mail :: Matchers
before ( :each ) do
Mail :: TestMailer . deliveries . clear
Mail . deliver do
to [ '[email protected]' , '[email protected]' ]
from '[email protected]'
subject 'testing'
body 'hello'
end
end
it { is_expected . to have_sent_email } # passes if any email at all was sent
it { is_expected . to have_sent_email . from ( '[email protected]' ) }
it { is_expected . to have_sent_email . to ( '[email protected]' ) }
# can specify a list of recipients...
it { is_expected . to have_sent_email . to ( [ '[email protected]' , '[email protected]' ] ) }
# ...or chain recipients together
it { is_expected . to have_sent_email . to ( '[email protected]' ) . to ( '[email protected]' ) }
it { is_expected . to have_sent_email . with_subject ( 'testing' ) }
it { is_expected . to have_sent_email . with_body ( 'hello' ) }
# Can match subject or body with a regex
# (or anything that responds_to? :match)
it { is_expected . to have_sent_email . matching_subject ( /test(ing)?/ ) }
it { is_expected . to have_sent_email . matching_body ( /h(a|e)llo/ ) }
# Can chain together modifiers
# Note that apart from recipients, repeating a modifier overwrites old value.
it { is_expected . to have_sent_email . from ( '[email protected]' ) . to ( '[email protected]' ) . matching_body ( /hell/ )
# test for attachments
# ... by specific attachment
it { is_expected . to have_sent_email . with_attachments ( my_attachment ) }
# ... or any attachment
it { is_expected . to have_sent_email . with_attachments ( any_attachment ) }
# ... or attachment with filename
it { is_expected . to have_sent_email . with_attachments ( an_attachment_with_filename ( 'file.txt' ) ) }
# ... or attachment with mime_type
it { is_expected . to have_sent_email . with_attachments ( an_attachment_with_mime_type ( 'application/pdf' ) ) }
# ... by array of attachments
it { is_expected . to have_sent_email . with_attachments ( [ my_attachment1 , my_attachment2 ] ) } #note that order is important
#... by presence
it { is_expected . to have_sent_email . with_any_attachments }
#... or by absence
it { is_expected . to have_sent_email . with_no_attachments }
end
File fixture spec di spec/fixture/emails/from_trec_2005 berasal dari Corpus Spam Publik TREC 2005. Mereka tetap memiliki hak cipta berdasarkan ketentuan proyek dan perjanjian lisensi tersebut. Mereka digunakan dalam proyek ini untuk memverifikasi dan menggambarkan pengembangan implementasi parser email ini.
http://plg.uwaterloo.ca/~gvcormac/treccorpus/
Mereka digunakan sebagaimana diizinkan oleh 'penggunaan yang diizinkan, Klausul 3':
"Small excerpts of the information may be displayed to others
or published in a scientific or technical context, solely for
the purpose of describing the research and development and
related issues."
-- http://plg.uwaterloo.ca/~gvcormac/treccorpus/
(Lisensi MIT)
Hak Cipta (C) 2009-2016 Mikel Lindsaar
Izin dengan ini diberikan, gratis, kepada siapa pun yang mendapatkan salinan perangkat lunak ini dan file dokumentasi terkait ('perangkat lunak'), untuk menangani perangkat lunak tanpa pembatasan, termasuk tanpa batasan hak untuk menggunakan, menyalin, memodifikasi, menggabungkan , menerbitkan, mendistribusikan, sublisense, dan/atau menjual salinan perangkat lunak, dan untuk mengizinkan orang -orang yang dilengkapi dengan perangkat lunak untuk melakukannya, tunduk pada kondisi berikut:
Pemberitahuan hak cipta di atas dan pemberitahuan izin ini harus dimasukkan dalam semua salinan atau bagian substansial dari perangkat lunak.
Perangkat lunak ini disediakan 'sebagaimana adanya', tanpa jaminan apa pun, tersurat maupun tersirat, termasuk tetapi tidak terbatas pada jaminan dapat diperjualbelikan, kebugaran untuk tujuan tertentu dan nonpringement. Dalam hal apa pun penulis atau pemegang hak cipta tidak akan bertanggung jawab atas klaim, kerusakan atau tanggung jawab lainnya, baik dalam tindakan kontrak, gugatan atau sebaliknya, timbul dari, di luar atau sehubungan dengan perangkat lunak atau penggunaan atau transaksi lain dalam PERANGKAT LUNAK.