O Mail é uma biblioteca da Internet para Ruby, projetada para lidar com a geração de email, analisar e enviar de uma maneira simples e rubiária.
O objetivo desta biblioteca é fornecer um único ponto de acesso para lidar com todas as funções de email, incluindo o envio e o recebimento de email. Todas as ações do tipo de rede são feitas por meio de métodos proxy para net :: smtp, net :: pop3 etc.
Construído a partir da minha experiência com o TMAIL, ele foi projetado para ser uma implementação pura do Ruby que torna a geração, o envio e a análise do email um acéfalo.
Também foi projetado desde o início para trabalhar com as versões mais modernas do Ruby. Os rubis modernos lidam com as codificações de texto de maneira muito mais maravilhosamente do que antes, portanto, esses recursos foram aproveitados ao máximo nesta biblioteca, permitindo que o e -mail lide com muito mais mensagens de maneira mais limpa que o Tmail.
Por fim, o e -mail foi projetado com um sistema de objetos muito simples que realmente abre as mensagens de email que você está analisando; se você souber o que está fazendo, pode mexer com todo o seu e -mail diretamente.
Sim, você! O correio é usado em inúmeros aplicativos por pessoas em todo o mundo. É, como todo o software de código aberto, um trabalho de amor de nosso tempo livre. Se você gostaria de agradecer, procure e contribua ao nosso lado! Triagem e corrija os problemas do Github, melhore nossa documentação, adicione novos recursos - até você! Obrigado por participar.
O correio é testado contra:
À medida que as novas versões do Ruby são lançadas, o email será compatível com o suporte para as versões "Preview" e All "Normal Manutenção", "Manutenção de Segurança" e as duas versões mais recentes "End of Life" listadas na página Rubiamento de Manutenção. Puxe solicitações para ajudar na adição de suporte para novos lançamentos de visualização são mais do que bem -vindos.
Cada compromisso de correio é testado por ações do GitHub em todas as versões do Ruby suportadas.
Se você deseja discutir e -mails com indivíduos semelhantes, assine o grupo do Google.
O Mail é compatível com RFC5322 e RFC6532 agora, ou seja, pode analisar o email US-ASCII e UTF-8 e gerar email US-ASCII. Existem algumas sintaxe de email obsoleta com as quais ela terá problemas, mas também é bastante robusta, ou seja, se encontrar algo que não entende que não travará, em vez disso, ele pulará o problema e continuará analisando. No caso de um cabeçalho que não entende, ele inicializará o cabeçalho como um campo não estruturado opcional e continuará analisando.
Isso significa que o e -mail não (nunca) tritura seus dados (eu acho).
Você também pode criar e -mails MIME. Existem métodos auxiliares para criar um email multipart/alternativo para texto/simples e texto/html (o par mais comum) e você pode criar manualmente qualquer outro tipo de email MIME.
Próximo TODO:
Basicamente ... nós fazemos BDD no correio. Nenhum método é escrito em correio sem uma especificação correspondente ou de cobertura. Esperamos como uma cobertura mínima de 100% medida pelo RCOV. Embora isso não seja perfeito em nenhuma medida, é muito bom. Além disso, todos os testes funcionais do Tmail devem passar antes que a gema seja lançada.
Isso também significa que você pode ter certeza de que o correio se comportará corretamente.
Você pode executar testes localmente executando bundle exec rspec
.
Você pode executar testes em todas as versões Ruby suportadas usando o ACT.
Nenhuma remoção de API dentro de uma única liberação de ponto. Todas as remoções a serem preteridas com avisos para pelo menos uma liberação de ponto menor antes da remoção.
Além disso, todos os métodos privados ou protegidos a serem declarados como tal - embora este ainda seja i/p.
A instalação é bastante simples, eu hospedo o correio em rubygems, para que você possa fazer:
# gem install mail
Se você não soubesse, o manuseio de codificações nos e -mails não é tão direto quanto você esperaria.
Eu tentei simplificar alguns:
Todos os objetos que podem renderizar em um email, têm um método #encoded
. A codificada retornará o objeto como uma string completa pronta para enviar no sistema de correio, ou seja, incluirá o campo do cabeçalho e o valor e o CRLF no final e embrulhado conforme necessário.
Todos os objetos que podem renderizar em um email, têm um método #decoded
. A decodificada retornará o "valor" do objeto apenas como uma string. Isso significa que não incluirá os campos de cabeçalho (como 'para:' ou 'sujeito:').
Por padrão, ligar #to_s
em um objeto de contêiner chamará seu método codificado, enquanto #to_s
em um objeto de campo chamará seu método decodificado. Portanto, ligar #to_s
em um objeto de email retornará o e -mail, todos codificados prontos para enviar, ao ligar para #to_s
no campo do campo ou o corpo retornará o valor decodificado do objeto. O objeto de cabeçalho do correio é considerado um contêiner. Em caso de dúvida, ligue para #encoded
ou #decoded
explicitamente, isso é mais seguro se você não tiver certeza.
Campos estruturados que possuem valores de parâmetros que podem ser codificados (por exemplo, tipo conteúdo) fornecerão valores de parâmetros decodificados quando você chamar os nomes dos parâmetros como métodos em relação ao objeto.
Campos estruturados que possuem valores de parâmetros que podem ser codificados (por exemplo, tipo conteúdo) fornecerão valores de parâmetros codificados quando você chama os nomes dos parâmetros através do object.parameters['<parameter_name>']
Chamada de método.
Por favor, faça! Contribuir é fácil no correio. Leia o documento contribuindo.md para obter mais informações.
Todas as principais funções de email devem poder acontecer no módulo de email. Portanto, você deve ser capaz de require 'mail'
para começar.
mail
está muito bem documentado em seu código Ruby. Você pode procurar, por exemplo, 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
O e-mail adicionará automaticamente um campo de ID da mensagem se estiver faltando e fornecerá um ID de mensagem aleatório e exclusivo ao longo das linhas de:
mail = Mail . new do
to '[email protected]'
message_id '<[email protected]>'
body 'Some simple body'
end
mail . to_s =~ /Message - ID: <[email protected]>/ #=> 27
O e -mail aceitará o Message_Id que você atribui a ele confiar que você sabe o que está fazendo.
Padrões de correio para enviar via SMTP para a porta host local 25. Se você tiver um Daemon Sendmail ou Postfix em execução nesta porta, o envio de email é tão fácil quanto:
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
ou
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!
Enviar via sendmail pode ser feito como assim:
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
Enviando via SMTP (por exemplo, para o correio)
Mail . defaults do
delivery_method :smtp , address : "localhost" , port : 1025
end
A EXIM requer seu próprio gerente de entrega e pode ser usado assim:
mail . delivery_method :exim , :location => "/usr/bin/exim"
mail . deliver
O correio também pode ser "entregue" a um arquivo de log para desenvolvimento e teste:
# 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
Você pode configurar o e -mail para receber e -mails usando retriever_method
no 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
Você pode acessar o email recebido de várias maneiras.
O e -mail mais recente:
Mail . all #=> Returns an array of all emails
Mail . first #=> Returns the first unread email
Mail . last #=> Returns the last unread email
Os 10 primeiros e -mails classificados por data em ordem crescente:
emails = Mail . find ( :what => :first , :count => 10 , :order => :asc )
emails . length #=> 10
Ou até todos os e -mails:
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...
Muitos outros métodos disponíveis.
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'}
O correio gera uma árvore de peças. Cada mensagem tem muitas ou nenhuma parte. Cada parte é outra mensagem que pode ter muitas ou nenhuma peça.
Uma mensagem terá apenas peças se for um tipo de conteúdo multipart/misto ou multipartrador/relacionado e tiver um limite definido.
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
O correio faz algumas suposições básicas e torna a coisa comum o mais simples possível ... (perguntando muito a partir de uma biblioteca de correio)
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
O Mail então entrega o e -mail no final do bloco e retorna o objeto de mensagem :: Mensagem resultante, que você pode inspecionar se deseja ...
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--
O correio insere a codificação de transferência de conteúdo, a versão MIME, os IDs de conteúdo e lida com o tipo de conteúdo e limite.
O Mail pressupõe que, se o seu texto no corpo for apenas US-ASCII, sua codificação de transferência é de 7 bits e é texto/simples. Você pode substituir isso declarando explicitamente.
Você não precisa usar um bloco com o texto e a parte HTML incluída, você pode fazer isso declarativamente. No entanto, você precisa adicionar e -mail :: peças a um email, não email :: mensagens.
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
Resulta no mesmo e -mail feito usando o formulário de bloco
@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
Você pode apenas ler o arquivo em um caminho absoluto, o e -mail tentará adivinhar o MIME_TYPE e codificará o arquivo no Base64 para você.
@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
Ou você pode passar em file_data e dar um nome de arquivo, novamente, o e -mail tentará adivinhar o MIME_TYPE para você.
@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
Você também pode substituir o tipo de mídia MIME adivinhada se realmente souber melhor do que o correio (isso raramente deve ser necessário)
@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'
Claro ... o correio também vai uma viagem de ida e volta
@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'
Consulte "Teste e extração de acessórios" acima para obter mais detalhes.
Se o correio fizer parte do seu sistema, você precisará de uma maneira de testá -lo sem realmente enviar e -mails, o Testmailer poderá fazer isso por você.
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
=> [ ]
Há também um conjunto de Matchers RSPEC roubados/inspirados pelos Matcores de Materia de Ação do Devora (você também deseja definir delivery_method
como acima):
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
Os arquivos de fixação do SPEC em SPEC/FIXTURES/EMAYS/From_Trec_2005 são do corpus de spam público TreC de 2005. Eles permanecem protegidos por direitos autorais sob os termos desse projeto e contrato de licença. Eles são usados neste projeto para verificar e descrever o desenvolvimento desta implementação do analisador de email.
http://plg.uwaterloo.ca/~gvcormac/treccorpus/
Eles são usados conforme permitido por 'usos permitidos, cláusula 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/
(A licença do MIT)
Copyright (C) 2009-2016 Mikel Lindsaar
A permissão é concedida, gratuita, a qualquer pessoa que obtenha uma cópia deste software e arquivos de documentação associados (o 'software'), para lidar com o software sem restrição, inclusive sem limitação os direitos de uso, copiar, modificar, mesclar, mesclar .
O aviso de direitos autorais acima e este aviso de permissão devem ser incluídos em todas as cópias ou em partes substanciais do software.
O software é fornecido 'como está', sem garantia de qualquer tipo, expresso ou implícito, incluindo, entre outros, as garantias de comercialização, aptidão para uma finalidade específica e não innoculação. Em nenhum caso os autores ou detentores de direitos autorais serão responsabilizados por qualquer reclamação, danos ou outro passivo, seja em uma ação de contrato, delito ou não, decorrente de, fora ou em conexão com o software ou o uso ou outras negociações nos Software.