Voglio scrivere un programma che manda email usando Python smtplib. Ho cercato attraverso il documento e le RFC, ma non ho trovato nulla relativo agli allegati. Quindi, sono sicuro che ci sia un concetto di livello superiore che mi sto perdendo. Qualcuno può indovinarmi su come funzionano gli allegati in SMTP?Come si inviano allegati tramite SMTP?
risposta
Quello che si desidera controllare è il modulo email
. Ti consente di creare i messaggi conformi a MIME che poi invii con smtplib.
Grazie per la modifica, eri un po 'più veloce di me ;-) –
Beh, gli allegati non sono trattati in alcun modo speciale, sono "solo" foglie dell'albero Message-oggetto. È possibile trovare le risposte a qualsiasi domanda riguardante i mesasges conformi a MIME nella sezione this della documentazione sul pacchetto python email.
In generale, qualsiasi tipo di allegato (leggi: dati binari non elaborati) può essere rappresentato utilizzando base64 (o simile) Content-Transfer-Encoding
.
Ecco un esempio che ho ritagliato da un'applicazione di lavoro che abbiamo creato. Crea un'e-mail HTML con un allegato Excel.
import smtplib,email,email.encoders,email.mime.text,email.mime.base
smtpserver = 'localhost'
to = ['[email protected]']
fromAddr = '[email protected]'
subject = "my subject"
# create html email
html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" '
html +='"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">'
html +='<body style="font-size:12px;font-family:Verdana"><p>...</p>'
html += "</body></html>"
emailMsg = email.MIMEMultipart.MIMEMultipart('alternative')
emailMsg['Subject'] = subject
emailMsg['From'] = fromAddr
emailMsg['To'] = ', '.join(to)
emailMsg['Cc'] = ", ".join(cc)
emailMsg.attach(email.mime.text.MIMEText(html,'html'))
# now attach the file
fileMsg = email.mime.base.MIMEBase('application','vnd.ms-excel')
fileMsg.set_payload(file('exelFile.xls').read())
email.encoders.encode_base64(fileMsg)
fileMsg.add_header('Content-Disposition','attachment;filename=anExcelFile.xls')
emailMsg.attach(fileMsg)
# send email
server = smtplib.SMTP(smtpserver)
server.sendmail(fromAddr,to,emailMsg.as_string())
server.quit()
Il sottotipo multipart deve essere "misto" anziché "alternativo" altrimenti non vedrai il file allegato in alcuni client di posta elettronica. – rhyek
Ecco come inviare e-mail con allegati di file ZIP e utf-8 soggetti codificato + corpo.
Non era semplice per calcolare questo fuori, per mancanza di documentazione e campioni per questo caso particolare.
caratteri non ASCII in replyto deve essere codificato con, per esempio, ISO-8859-1. Probabilmente esiste una funzione che può farlo.
Suggerimento:
Invia anche tu una e-mail, salvarla ed esaminare il contenuto di capire come fare la stessa cosa in Python.
Ecco il codice, per Python 3:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:set ts=4 sw=4 et:
from os.path import basename
from smtplib import SMTP
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.utils import parseaddr, formataddr
from base64 import encodebytes
def send_email(recipients=["[email protected]"],
subject="Test subject æøå",
body="Test body æøå",
zipfiles=[],
server="smtp.somewhere.xyz",
username="bob",
password="password123",
sender="Bob <[email protected]>",
replyto="=?ISO-8859-1?Q?M=F8=F8=F8?= <[email protected]>"): #: bool
"""Sends an e-mail"""
to = ",".join(recipients)
charset = "utf-8"
# Testing if body can be encoded with the charset
try:
body.encode(charset)
except UnicodeEncodeError:
print("Could not encode " + body + " as " + charset + ".")
return False
# Split real name (which is optional) and email address parts
sender_name, sender_addr = parseaddr(sender)
replyto_name, replyto_addr = parseaddr(replyto)
sender_name = str(Header(sender_name, charset))
replyto_name = str(Header(replyto_name, charset))
# Create the message ('plain' stands for Content-Type: text/plain)
try:
msgtext = MIMEText(body.encode(charset), 'plain', charset)
except TypeError:
print("MIMEText fail")
return False
msg = MIMEMultipart()
msg['From'] = formataddr((sender_name, sender_addr))
msg['To'] = to #formataddr((recipient_name, recipient_addr))
msg['Reply-to'] = formataddr((replyto_name, replyto_addr))
msg['Subject'] = Header(subject, charset)
msg.attach(msgtext)
for zipfile in zipfiles:
part = MIMEBase('application', "zip")
b = open(zipfile, "rb").read()
# Convert from bytes to a base64-encoded ascii string
bs = encodebytes(b).decode()
# Add the ascii-string to the payload
part.set_payload(bs)
# Tell the e-mail client that we're using base 64
part.add_header('Content-Transfer-Encoding', 'base64')
part.add_header('Content-Disposition', 'attachment; filename="%s"' %
os.path.basename(zipfile))
msg.attach(part)
s = SMTP()
try:
s.connect(server)
except:
print("Could not connect to smtp server: " + server)
return False
if username:
s.login(username, password)
print("Sending the e-mail")
s.sendmail(sender, recipients, msg.as_string())
s.quit()
return True
def main():
send_email()
if __name__ == "__main__":
main()
Ecco un esempio di un messaggio con un allegato PDF, un testo "corpo" e l'invio tramite Gmail.
# Import smtplib for the actual sending function
import smtplib
# For guessing MIME type
import mimetypes
# Import the email modules we'll need
import email
import email.mime.application
# Create a text/plain message
msg = email.mime.Multipart.MIMEMultipart()
msg['Subject'] = 'Greetings'
msg['From'] = '[email protected]'
msg['To'] = '[email protected]'
# The main body is just another attachment
body = email.mime.Text.MIMEText("""Hello, how are you? I am fine.
This is a rather nice letter, don't you think?""")
msg.attach(body)
# PDF attachment
filename='simple-table.pdf'
fp=open(filename,'rb')
att = email.mime.application.MIMEApplication(fp.read(),_subtype="pdf")
fp.close()
att.add_header('Content-Disposition','attachment',filename=filename)
msg.attach(att)
# send via Gmail server
# NOTE: my ISP, Centurylink, seems to be automatically rewriting
# port 25 packets to be port 587 and it is trashing port 587 packets.
# So, I use the default port 25, but I authenticate.
s = smtplib.SMTP('smtp.gmail.com')
s.starttls()
s.login('[email protected]','xyzpassword')
s.sendmail('[email protected]',['[email protected]'], msg.as_string())
s.quit()
Questo ha risolto il mio problema per l'invio tramite e-mail di file excel, il che è stato fantastico perché mi ha tenuto fuori da os.system chiamando Ruby! Grazie Kevin! – Benjooster
Questa soluzione ha funzionato anche per me, dopo aver creato un file .xls usando il modulo xlwt Python. Invece di inviare Gmail ho utilizzato il server di posta della mia azienda. Grazie, e +1 –
questo metodo ha funzionato davvero ed è molto più pulito! –
# -*- coding: utf-8 -*-
"""
Mail sender
"""
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
import pystache
import codecs
import time
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
HOST = 'smtp.exmail.qq.com'
PORT = 587
USER = '[email protected]'
PASS = 'yourpass'
FROM = '[email protected]'
SUBJECT = 'subject'
HTML_NAME = 'tpl.html'
CSV_NAME = 'list.txt'
FAILED_LIST = []
def send(mail_receiver, mail_to):
# text = mail_text
html = render(mail_receiver)
# msg = MIMEMultipart('alternative')
msg = MIMEMultipart('mixed')
msg['From'] = FROM
msg['To'] = mail_to.encode()
msg['Subject'] = SUBJECT.encode()
# msg.attach(MIMEText(text, 'plain', 'utf-8'))
msg.attach(MIMEText(html, 'html', 'utf-8'))
try:
_sender = smtplib.SMTP(
HOST,
PORT
)
_sender.starttls()
_sender.login(USER, PASS)
_sender.sendmail(FROM, mail_to, msg.as_string())
_sender.quit()
print "Success"
except smtplib.SMTPException, e:
print e
FAILED_LIST.append(mail_receiver + ',' + mail_to)
def render(name):
_tpl = codecs.open(
'./html/' + HTML_NAME,
'r',
'utf-8'
)
_html_string = _tpl.read()
return pystache.render(_html_string, {
'receiver': name
})
def main():
ls = open('./csv/' + CSV_NAME, 'r')
mail_list = ls.read().split('\r')
for _receiver in mail_list:
_tmp = _receiver.split(',')
print 'Mail: ' + _tmp[0] + ',' + _tmp[1]
time.sleep(20)
send(_tmp[0], _tmp[1])
print FAILED_LIST
main()
- 1. Come si inviano caratteri speciali tramite SendKeys?
- 2. Il messaggio corpo non viene visualizzato quando si inviano allegati
- 3. Come si inviano i dati tramite il metodo GET?
- 4. Più allegati tramite phpmailer
- 5. gmail conversazione tramite SMTP
- 6. inviare email tramite Gmail SMTP
- 7. C# Invio SMTP tramite System.Threading
- 8. Invio di allegati di posta tramite Java
- 9. . Coda SMTP SMTP
- 10. Linq ChangeConflictException si verifica quando si inviano modifiche DataContext
- 11. Errore nell'invio di e-mail tramite SMTP
- 12. Inviare e-mail tramite SMTP Zoho
- 13. Come inviare e-mail tramite Exchange Server senza usare smtp?
- 14. Invio di e-mail con allegati da C#, gli allegati arrivano come parte 1.2 in Thunderbird
- 15. Come si inviano più parametri in un Url.Azione?
- 16. Come si chiude un canale che inviano più goroutine?
- 17. Come si inviano i dati POST con LWP?
- 18. Come si inviano le intestazioni UpperCase in HTTP
- 19. Come implementare l'ID mittente quando si inviano mail attraverso C#?
- 20. Come si inviano le carte raggruppate tutte nello stesso momento?
- 21. Assegnare un nome all'account e-mail quando si inviano e-mail con Django tramite Google Apps
- 22. Quanto può essere grande il carico utile quando si inviano dati tramite WatchConnectivity?
- 23. Che cosa causa l'errore Skrill LOCK_LEVEL_9 quando si inviano soldi?
- 24. Allegati e-mail multipli di Android tramite Intento
- 25. CouchDB on-the-fly allegati tramite riga di comando
- 26. Invio di email da Django tramite SMTP ospitato
- 27. python non può inviare file allegati tramite e-mail
- 28. Invio di e-mail SMTP tramite Django nell'ambiente di produzione
- 29. Linux: quando si inviano frame Ethernet, l'ethertype viene riscritto
- 30. Invio di e-mail tramite server smtp in JAVA
Giusto per essere chiari, non c'è nulla in SMTP per gestire questa situazione, è interamente gestita da strutturare il documento viene inviato come documento MIME. L'articolo su MIME su wikipedia sembra coprire abbastanza bene la base. – jcoder
Includere un collegamento direttamente nella sezione "esempi email" dei documenti Python renderebbe qualsiasi risposta completa: http://docs.python.org/library/email-examples.html –