email send - Come inviare una mail con Python?





raspberry login (10)


Bene, vuoi avere una risposta aggiornata e moderna.

Ecco la mia risposta:

Quando ho bisogno di spedire mail in python, io uso l'API mailgun che ottiene un sacco di grattacapi con l'invio di mail risolte. Hanno un'app / API meravigliosa che ti consente di inviare 10.000 email al mese gratuitamente.

L'invio di un'email sarebbe come questo:

def send_simple_message():
    return requests.post(
        "https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/messages",
        auth=("api", "YOUR_API_KEY"),
        data={"from": "Excited User <[email protected]_DOMAIN_NAME>",
              "to": ["[email protected]", "[email protected]_DOMAIN_NAME"],
              "subject": "Hello",
              "text": "Testing some Mailgun awesomness!"})

Puoi anche tenere traccia degli eventi e molto altro, vedere la guida rapida .

Spero che tu trovi questo utile!

Questo codice funziona e mi invia una e-mail bene:

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()

Tuttavia se provo a racchiuderlo in una funzione come questa:

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 chiamalo ottengo i seguenti errori:

 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

Qualcuno può aiutarmi a capire perché?




Vi consiglio di utilizzare i pacchetti standard email e smtplib insieme per inviare e-mail. Si prega di guardare l'esempio seguente (riprodotto dalla documentazione di Python ). Si noti che se si segue questo approccio, il compito "semplice" è davvero semplice e le attività più complesse (come il collegamento di oggetti binari o l'invio di messaggi in multiparte semplici / HTML) vengono eseguite molto rapidamente.

# Import smtplib for the actual sending function
import smtplib

# Import the email modules we'll need
from email.mime.text import MIMEText

# Open a plain text file for reading.  For this example, assume that
# the text file contains only ASCII characters.
with open(textfile, 'rb') as fp:
    # Create a text/plain message
    msg = MIMEText(fp.read())

# me == the sender's email address
# you == the recipient's email address
msg['Subject'] = 'The contents of %s' % textfile
msg['From'] = me
msg['To'] = you

# Send the message via our own SMTP server, but don't include the
# envelope header.
s = smtplib.SMTP('localhost')
s.sendmail(me, [you], msg.as_string())
s.quit()

Per inviare e-mail a più destinazioni, puoi anche seguire l'esempio nella documentazione di Python :

# Import smtplib for the actual sending function
import smtplib

# Here are the email package modules we'll need
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart

# Create the container (outer) email message.
msg = MIMEMultipart()
msg['Subject'] = 'Our family reunion'
# me == the sender's email address
# family = the list of all recipients' email addresses
msg['From'] = me
msg['To'] = ', '.join(family)
msg.preamble = 'Our family reunion'

# Assume we know that the image files are all in PNG format
for file in pngfiles:
    # Open the files in binary mode.  Let the MIMEImage class automatically
    # guess the specific image type.
    with open(file, 'rb') as fp:
        img = MIMEImage(fp.read())
    msg.attach(img)

# Send the email via our own SMTP server.
s = smtplib.SMTP('localhost')
s.sendmail(me, family, msg.as_string())
s.quit()

Come puoi vedere, l'intestazione To nell'oggetto MIMEText deve essere una stringa composta da indirizzi email separati da virgole. D'altra parte, il secondo argomento della funzione sendmail deve essere una lista di stringhe (ogni stringa è un indirizzo email).

Pertanto, se hai tre indirizzi email: [email protected] , [email protected] e [email protected] , puoi procedere come segue (le sezioni ovvie sono omesse):

to = ["[email protected]", "[email protected]", "[email protected]"]
msg['To'] = ",".join(to)
s.sendmail(me, to, msg.as_string())

la parte "","".join(to) rende una singola stringa fuori dalla lista, separata da virgole.

Dalle tue domande deduco che non hai seguito il tutorial di Python - è un MUST se vuoi arrivare ovunque in Python - la documentazione è in gran parte eccellente per la libreria standard.




Mentre indentate il vostro codice nella funzione (che è ok), avete anche fatto rientrare le righe della stringa di messaggio non elaborata. Ma lo spazio bianco principale implica la piegatura (concatenazione) delle linee di intestazione, come descritto nelle sezioni 2.2.3 e 3.2.3 di RFC 2822 - Formato messaggio Internet :

Ogni campo di intestazione è logicamente una singola riga di caratteri che comprende il nome del campo, i due punti e il corpo del campo. Per comodità, tuttavia, e per gestire le limitazioni di 998/78 caratteri per riga, la porzione di campo di un campo di intestazione può essere suddivisa in una rappresentazione a più righe; questo è chiamato "pieghevole".

Nella forma di funzione della tua chiamata sendmail , tutte le linee iniziano con uno spazio bianco e quindi sono "unfolded" (concatenate) e stai provando ad inviare

From: [email protected]    To: [email protected]    Subject: Hello!    This message was sent with Python's smtplib.

A parte la nostra ipotesi, smtplib non capirà più le intestazioni To: and Subject: perché questi nomi vengono riconosciuti solo all'inizio di una riga. Invece smtplib assumerà un indirizzo email del mittente molto lungo:

[email protected]    To: [email protected]    Subject: Hello!    This message was sent with Python's smtplib.

Questo non funzionerà e così viene la tua eccezione.

La soluzione è semplice: basta conservare la stringa del message come era prima. Questo può essere fatto con una funzione (come suggerito da Zeeshan) o immediatamente nel codice sorgente:

import smtplib

def sendMail(FROM,TO,SUBJECT,TEXT,SERVER):
    """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()

Ora lo spiegamento non si verifica e tu mandi

From: [email protected]
To: [email protected]
Subject: Hello!

This message was sent with Python's smtplib.

che è ciò che funziona e cosa è stato fatto con il tuo vecchio codice.

Nota che stavo anche conservando la linea vuota tra intestazioni e corpo per adattare la sezione 3.5 della RFC (che è richiesta) e metti l'inclusione al di fuori della funzione secondo la guida in stile Python PEP-0008 (che è opzionale).




C'è un problema di indentazione. Il codice seguente funzionerà:

import textwrap

def sendMail(FROM,TO,SUBJECT,TEXT,SERVER):
    import smtplib
    """this is some test documentation in the function"""
    message = textwrap.dedent("""\
        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()



Mi piacerebbe aiutarti con l'invio di e-mail consigliando il pacchetto yagmail (sono il manutentore, mi dispiace per la pubblicità, ma credo che possa davvero aiutarti!).

L'intero codice per te sarebbe:

import yagmail
yag = yagmail.SMTP(FROM, 'pass')
yag.send(TO, SUBJECT, TEXT)

Nota che fornisco i valori predefiniti per tutti gli argomenti, ad esempio se vuoi inviarti a te stesso, puoi omettere TO , se non vuoi un argomento, puoi anche ometterlo.

Inoltre, l'obiettivo è anche quello di rendere molto semplice l'aggiunta di codice HTML o immagini (e altri file).

Dove inserisci contenuti puoi fare qualcosa come:

contents = ['Body text, and here is an embedded image:', 'http://somedomain/image.png',
            'You can also find an audio file attached.', '/local/path/song.mp3']

Wow, quanto è facile inviare allegati! Ciò richiederebbe 20 linee senza yagmail;)

Inoltre, se lo si imposta una volta, non sarà più necessario inserire nuovamente la password (e salvarla in modo sicuro). Nel tuo caso puoi fare qualcosa come:

import yagmail
yagmail.SMTP().send(contents = contents)

che è molto più conciso!

Ti inviterei a dare un'occhiata al yagmail o installarlo direttamente con pip install yagmail .




Ho pensato di mettere i miei due bit qui da quando ho appena capito come funziona.

Sembra che tu non abbia la porta specificata nelle impostazioni di connessione SERVER, questo mi ha un po 'influenzato quando stavo cercando di connettermi al mio server SMTP che non usa la porta predefinita: 25.

Secondo i documenti smtplib.SMTP, la tua richiesta / risposta ehlo o helo dovrebbe essere automaticamente presa in considerazione, quindi non dovresti preoccuparti di questo (ma potrebbe essere qualcosa da confermare se tutto il resto fallisce).

Un'altra cosa da chiedersi è che hai permesso connessioni SMTP sul tuo server SMTP stesso? Per alcuni siti come GMAIL e ZOHO devi effettivamente entrare e attivare le connessioni IMAP all'interno dell'account e-mail. Il tuo server di posta potrebbe non consentire connessioni SMTP che non provengono da "localhost", forse? Qualcosa da esaminare.

L'ultima cosa è che potresti voler provare e iniziare la connessione su TLS. La maggior parte dei server ora richiede questo tipo di autenticazione.

Vedrai che ho bloccato due campi TO nella mia email. Le voci msg ['TO'] e msg ['FROM'] del dizionario msg permettono di mostrare le informazioni corrette nelle intestazioni dell'email stessa, che si vede sul lato ricevente dell'email nei campi To / From (tu potrebbe anche essere in grado di aggiungere un campo Rispondi a qui. I campi TO e FROM stessi sono ciò che richiede il server. So di aver sentito alcuni server e-mail rifiutare le e-mail se non hanno le intestazioni e-mail corrette in atto.

Questo è il codice che ho usato, in una funzione, che funziona per me per inviare via email il contenuto di un file * .txt usando il mio computer locale e un server SMTP remoto (ZOHO come mostrato):

def emailResults(folder, filename):

    # body of the message
    doc = folder + filename + '.txt'
    with open(doc, 'r') as readText:
        msg = MIMEText(readText.read())

    # headers
    TO = '[email protected]'
    msg['To'] = TO
    FROM = '[email protected]'
    msg['From'] = FROM
    msg['Subject'] = 'email subject |' + filename

    # SMTP
    send = smtplib.SMTP('smtp.zoho.com', 587)
    send.starttls()
    send.login('[email protected]', 'password')
    send.sendmail(FROM, TO, msg.as_string())
    send.quit()



Probabilmente sta mettendo le schede nel tuo messaggio. Stampa il messaggio prima di passarlo a sendMail.




Ecco un esempio su Python 3.x , molto più semplice di 2.x :

import smtplib
from email.message import EmailMessage
def send_mail(to_email, subject, message, server='smtp.example.cn',
              from_email='[email protected]'):
    # import smtplib
    msg = EmailMessage()
    msg['Subject'] = subject
    msg['From'] = from_email
    msg['To'] = ', '.join(to_email)
    msg.set_content(message)
    print(msg)
    server = smtplib.SMTP(server)
    server.set_debuglevel(1)
    server.login(from_email, 'password')  # user & password
    server.send_message(msg)
    server.quit()
    print('successfully sent the mail.')

chiama questa funzione:

send_mail(to_email=['[email protected]', '[email protected]'],
          subject='hello', message='Your analysis has done!')

sotto può solo per utente cinese:

Se usi 126/163, 网易 邮箱, devi impostare "客户 端 授权 密码", come di seguito:

ref: https://.com/a/41470149/2803344 https://docs.python.org/3/library/email.examples.html#email-examples




Prova questo:

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)
    "New part"
    server.starttls()
    server.login('username', 'password')
    server.sendmail(FROM, TO, message)
    server.quit()

Funziona per smtp.gmail.com




Ecco una discussione molto buona sull'uso di espressioni regolari per convalidare gli indirizzi email; " http://fightingforalostcause.net/misc/2006/compare-email-regex.php "

Ecco l'espressione principale corrente, che è compatibile con JavaScript, a fini di riferimento:

/^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i






python email function smtplib