Esse código funciona e me envia um email muito bem:
import smtplib
#SERVER = "localhost"
FROM = '[email protected]'
TO = ["[email protected]"] # must be a list
SUBJECT = "Hello!"
TEXT = "This message was sent with Python's smtplib."
# Prepare actual message
message = """\
From: %s
To: %s
Subject: %s
%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
# Send the mail
server = smtplib.SMTP('myserver')
server.sendmail(FROM, TO, message)
server.quit()
No entanto, se eu tentar envolvê-lo em uma função como esta:
def sendMail(FROM,TO,SUBJECT,TEXT,SERVER):
import smtplib
"""this is some test documentation in the function"""
message = """\
From: %s
To: %s
Subject: %s
%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
# Send the mail
server = smtplib.SMTP(SERVER)
server.sendmail(FROM, TO, message)
server.quit()
e chamá-lo, recebo os seguintes erros:
Traceback (most recent call last):
File "C:/Python31/mailtest1.py", line 8, in <module>
sendmail.sendMail(sender,recipients,subject,body,server)
File "C:/Python31\sendmail.py", line 13, in sendMail
server.sendmail(FROM, TO, message)
File "C:\Python31\lib\smtplib.py", line 720, in sendmail
self.rset()
File "C:\Python31\lib\smtplib.py", line 444, in rset
return self.docmd("rset")
File "C:\Python31\lib\smtplib.py", line 368, in docmd
return self.getreply()
File "C:\Python31\lib\smtplib.py", line 345, in getreply
raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed
Alguém pode me ajudar a entender o porquê?
Respostas:
Eu recomendo que você use os pacotes padrão
email
esmtplib
juntos para enviar email. Por favor, veja o exemplo a seguir (reproduzido da documentação do Python ). Observe que, se você seguir essa abordagem, a tarefa "simples" é realmente simples, e as tarefas mais complexas (como anexar objetos binários ou enviar mensagens de várias partes sem formatação / HTML) são realizadas muito rapidamente.Para enviar email para vários destinos, você também pode seguir o exemplo na documentação do Python :
Como você pode ver, o cabeçalho
To
doMIMEText
objeto deve ser uma sequência que consiste em endereços de email separados por vírgulas. Por outro lado, o segundo argumento para asendmail
função deve ser uma lista de cadeias (cada cadeia é um endereço de email).Então, se você tem três endereços de email:
[email protected]
,[email protected]
e[email protected]
, você pode fazer o seguinte (seções óbvias omitido):a
",".join(to)
peça cria uma única string fora da lista, separada por vírgulas.A partir das suas perguntas, entendo que você não passou pelo tutorial do Python - é OBRIGATÓRIO se você quiser chegar a algum lugar no Python - a documentação é principalmente excelente para a biblioteca padrão.
fonte
", ".join(["[email protected]", "[email protected]"])
with
:with open(textfile, 'rb') as fp:
. O fechamento explícito pode ser eliminado, pois owith
bloco fechará o arquivo mesmo que ocorra um erro dentro dele.Bem, você quer ter uma resposta atualizada e moderna.
Aqui está a minha resposta:
Quando preciso enviar e-mail em python, uso a API mailgun, que causa muitas dores de cabeça ao enviar e-mails resolvidos. Eles têm um maravilhoso aplicativo / API que permite enviar 10.000 e-mails por mês gratuitamente.
O envio de um email seria assim:
Você também pode acompanhar eventos e muito mais, consulte o guia de início rápido .
Espero que você ache isso útil!
fonte
Gostaria de ajudá-lo a enviar e-mails, aconselhando o pacote yagmail (sou o mantenedor, desculpe a publicidade, mas acho que ela pode realmente ajudar!).
O código inteiro para você seria:
Observe que eu forneço padrões para todos os argumentos; por exemplo, se você deseja enviar para si mesmo, pode omitir
TO
; se não quiser um assunto, também pode omitir.Além disso, o objetivo também é facilitar a anexação de códigos ou imagens html (e outros arquivos).
Onde você coloca o conteúdo, pode fazer algo como:
Uau, como é fácil enviar anexos! Isso levaria 20 linhas sem o yagmail;)
Além disso, se você a configurar uma vez, nunca precisará digitar a senha novamente (e armazená-la com segurança). No seu caso, você pode fazer algo como:
o que é muito mais conciso!
Convido você a dar uma olhada no github ou instalá-lo diretamente com
pip install yagmail
.fonte
yagmail
outro que não o gmail? Estou tentando usar para o meu próprio servidor SMTP.Attachment
classe; ainda é a mesma coisa. Se eles puderem alterar o seu código, poderão fazer o que quiserem (com / sem raiz, é o mesmo envio de e-mail por escrito). Isso me parece o típico "é conveniente / mágico, portanto deve ser menos seguro". Estou curioso que ameaça real você vê?Há um problema de recuo. O código abaixo funcionará:
fonte
SERVER
variável que é passada para a função são as credenciais do usuário.email
biblioteca Python faz isso razoavelmente bem (principalmente desde a 3.6), embora ainda exija alguma compreensão do que você está fazendo.Aqui está um exemplo no Python
3.x
, muito mais simples que2.x
:chame esta função:
abaixo pode apenas para o usuário chinês:
Se você usar 126/163, 网易 邮箱, precisará definir "客户 端 授权 密码", como abaixo:
ref: https://stackoverflow.com/a/41470149/2803344 https://docs.python.org/3/library/email.examples.html#email-examples
fonte
Ao recuar seu código na função (o que está ok), você também recuou as linhas da cadeia de mensagens brutas. Mas o espaço em branco à esquerda implica dobrar (concatenação) das linhas de cabeçalho, conforme descrito nas seções 2.2.3 e 3.2.3 da RFC 2822 - Internet Message Format :
Na forma de função da sua
sendmail
chamada, todas as linhas começam com espaço em branco e, portanto, são "desdobradas" (concatenadas) e você está tentando enviarAlém do que nossa mente sugere,
smtplib
não entenderá mais os cabeçalhosTo:
eSubject:
, porque esses nomes são reconhecidos apenas no início de uma linha. Em vez dissosmtplib
, assumirá um endereço de email do remetente muito longo:Isso não vai funcionar e a exceção é sua.
A solução é simples: basta preservar a
message
string como era antes. Isso pode ser feito por uma função (como Zeeshan sugeriu) ou imediatamente no código-fonte:Agora o desdobramento não ocorre e você envia
que é o que funciona e o que foi feito pelo seu código antigo.
Observe também que eu estava preservando a linha vazia entre os cabeçalhos e o corpo para acomodar a seção 3.5 da RFC (que é necessária) e colocar o include fora da função, de acordo com o guia de estilo Python PEP-0008 (que é opcional).
fonte
Provavelmente, está colocando abas na sua mensagem. Imprima a mensagem antes de passá-la para sendMail.
fonte
Verifique se você concedeu permissão ao remetente e ao destinatário para enviar e-mail de fontes desconhecidas (fontes externas) na conta de e-mail.
fonte
msg
não é uma mensagem SMTP válida e simplesmente parecerá desaparecer no éter se o seu servidor de email aceitar.Pensei em colocar meus dois bits aqui desde que acabei de descobrir como isso funciona.
Parece que você não tem a porta especificada nas configurações de conexão do SERVIDOR, isso me afetou um pouco quando eu estava tentando conectar-me ao meu servidor SMTP que não está usando a porta padrão: 25.
De acordo com os documentos smtplib.SMTP, sua solicitação / resposta ehlo ou helo deve ser atendida automaticamente, para que você não precise se preocupar com isso (mas pode ser algo para confirmar se tudo falhar).
Outra coisa a se perguntar é que você permitiu conexões SMTP no próprio servidor SMTP? Para alguns sites como GMAIL e ZOHO, você precisa realmente ativar e ativar as conexões IMAP na conta de email. Seu servidor de email pode não permitir conexões SMTP que não provêm de 'localhost', talvez? Algo para investigar.
A última coisa é que você pode tentar iniciar a conexão no TLS. A maioria dos servidores agora exige esse tipo de autenticação.
Você verá que eu coloquei dois campos TO no meu e-mail. Os itens de dicionário msg ['TO'] e msg ['FROM'] msg permitem que as informações corretas sejam exibidas nos cabeçalhos do próprio email, que são vistas na extremidade de recebimento do email nos campos Para / De (você pode até ser capaz de adicionar um campo Responder a aqui.Os campos TO e FROM são o que o servidor exige.Eu sei que ouvi alguns servidores de email rejeitando emails se eles não tiverem os cabeçalhos de email adequados.
Este é o código que eu usei, em uma função, que funciona para eu enviar por e-mail o conteúdo de um arquivo * .txt usando meu computador local e um servidor SMTP remoto (ZOHO, como mostrado):
fonte
Vale ressaltar que o módulo SMTP suporta o gerenciador de contexto, portanto, não há necessidade de chamar manualmente quit (), isso garantirá que ele sempre seja chamado, mesmo que haja uma exceção.
fonte
No que diz respeito ao seu código, não parece haver nada de fundamentalmente errado, exceto que não está claro como você está realmente chamando essa função. Tudo o que consigo pensar é que, quando o servidor não está respondendo, você receberá esse erro SMTPServerDisconnected. Se você procurar a função getreply () no smtplib (trecho abaixo), terá uma ideia.
verifique um exemplo em https://github.com/rreddy80/sendEmails/blob/master/sendEmailAttachments.py que também usa uma chamada de função para enviar um email, se é isso que você está tentando fazer (abordagem DRY).
fonte