Ten kod działa i dobrze wysyła mi e-mail:
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()
Jeśli jednak spróbuję zawinąć go w taką funkcję:
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()
i nazwij to otrzymuję następujące błędy:
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
Czy ktoś może mi pomóc zrozumieć, dlaczego?
Odpowiedzi:
Polecam korzystać ze standardowych pakietów
email
ismtplib
wspólnie wysyłać e-maile. Proszę spojrzeć na następujący przykład (odtworzony z dokumentacji Pythona ). Zauważ, że jeśli zastosujesz to podejście, „proste” zadanie jest rzeczywiście proste, a bardziej złożone zadania (takie jak dołączanie obiektów binarnych lub wysyłanie zwykłych / wieloczęściowych wiadomości HTML) są wykonywane bardzo szybko.Aby wysłać wiadomość e-mail do wielu miejsc docelowych, możesz również postępować zgodnie z przykładem w dokumentacji Pythona :
Jak widać, nagłówek
To
wMIMEText
obiekcie musi być ciąg składający się z adresów e-mail oddzielonych przecinkami. Z drugiej strony drugi argument dosendmail
funkcji musi być lista ciągów (każdy ciąg to adres e-mail).Tak więc, jeśli masz trzy adresy e-mail:
[email protected]
,[email protected]
, i[email protected]
, można to zrobić w następujący sposób (oczywiste sekcje pominięte):",".join(to)
część sprawia, że jeden ciąg z listy, oddzielonych przecinkami.Z twoich pytań wynika, że nie przeszedłeś przez samouczek Pythona - jest to KONIECZNOŚĆ, jeśli chcesz dostać się gdziekolwiek w Pythonie - dokumentacja jest w większości doskonała dla standardowej biblioteki.
źródło
", ".join(["[email protected]", "[email protected]"])
with
:with open(textfile, 'rb') as fp:
. Można porzucić jawne zamknięcie, ponieważwith
blok zamknie plik, nawet jeśli wystąpi w nim błąd.Cóż, chcesz mieć odpowiedź, która jest aktualna i nowoczesna.
Oto moja odpowiedź:
Kiedy muszę wysyłać pocztę w Pythonie, używam API mailgun, które powoduje wiele problemów związanych z wysyłaniem poczty. Mają cudowną aplikację / interfejs API, która umożliwia bezpłatne wysyłanie 10000 e-maili miesięcznie.
Wysłanie wiadomości e-mail wyglądałoby tak:
Możesz także śledzić zdarzenia i wiele więcej, zobacz przewodnik Szybki start .
Mam nadzieję, że okaże się to przydatne!
źródło
Chciałbym pomóc Ci w wysyłaniu e-maili, doradzając pakiet yagmail (jestem opiekunem, przepraszam za reklamy, ale czuję, że to naprawdę może pomóc!).
Cały kod byłby dla Ciebie:
Zauważ, że podaję wartości domyślne dla wszystkich argumentów, na przykład, jeśli chcesz wysłać do siebie, możesz pominąć
TO
, jeśli nie chcesz, możesz go również pominąć.Ponadto celem jest również ułatwienie dołączania kodu HTML lub obrazów (i innych plików).
Tam, gdzie umieścisz zawartość, możesz zrobić coś takiego:
Wow, jak łatwo jest wysyłać załączniki! To zajęłoby około 20 linii bez yagmaila;)
Ponadto, jeśli skonfigurujesz je raz, nigdy nie będziesz musiał ponownie wprowadzać hasła (i bezpiecznie je przechowywać). W twoim przypadku możesz zrobić coś takiego:
co jest o wiele bardziej zwięzłe!
Zapraszam do obejrzenia github lub zainstalowania go bezpośrednio za pomocą
pip install yagmail
.źródło
yagmail
innego niż Gmaila? Próbuję użyć własnego serwera SMTP.Attachment
klasę; to wciąż to samo. Jeśli mogą zmienić twój kod, to i tak mogą zrobić wszystko, co chcą (z / bez roota, to jest to samo, co wysyłanie e-maili). Wydaje mi się, że to typowe „jest wygodne / magiczne, więc musi być mniej bezpieczne”. Ciekaw jestem, jakie prawdziwe zagrożenie widzisz?Występuje problem z wcięciami. Poniższy kod zadziała:
źródło
SERVER
zmienną przekazywaną do funkcji są poświadczenia użytkownika.email
Biblioteka Pythona robi to dość dobrze (szczególnie od 3.6), chociaż nadal wymaga pewnego zrozumienia tego, co robisz.Oto przykład w Pythonie
3.x
, znacznie prostszy niż2.x
:wywołaj tę funkcję:
poniżej może tylko dla chińskiego użytkownika:
Jeśli używasz 126/163, 网易 邮箱, musisz ustawić „客户 端 授权 密码”, jak poniżej:
ref: https://stackoverflow.com/a/41470149/2803344 https://docs.python.org/3/library/email.examples.html#email-examples
źródło
Podczas wcięcia kodu w funkcji (co jest w porządku), wciąłeś również wiersze nieprzetworzonego ciągu wiadomości. Ale wiodące białe znaki oznaczają zwijanie (konkatenację) wierszy nagłówka, jak opisano w sekcjach 2.2.3 i 3.2.3 RFC 2822 - Internet Message Format :
W formie funkcji
sendmail
wywołania wszystkie linie rozpoczynają się od spacji, więc są „rozwijane” (łączone) i próbujesz wysłaćInaczej niż sugeruje nasz umysł,
smtplib
nie zrozumie już nagłówkówTo:
iSubject:
, ponieważ te nazwy są rozpoznawane tylko na początku wiersza. Zamiast tegosmtplib
przyjmie bardzo długi adres e-mail nadawcy:To nie zadziała, więc przychodzi Twój wyjątek.
Rozwiązanie jest proste: po prostu zachowaj
message
sznurek tak, jak był wcześniej. Można to zrobić za pomocą funkcji (jak sugerował Zeeshan) lub od razu w kodzie źródłowym:Teraz rozwijanie nie następuje i wysyłasz
co działa i co zostało zrobione przez twój stary kod.
Zauważ, że zachowałem również pustą linię między nagłówkami i treścią, aby pomieścić sekcję 3.5 specyfikacji RFC (która jest wymagana) i umieściłem dołączenie poza funkcją zgodnie z przewodnikiem stylu Pythona PEP-0008 (który jest opcjonalny).
źródło
Prawdopodobnie umieszcza w wiadomości tabulatory. Wydrukuj wiadomość, zanim przekażesz ją do sendMail.
źródło
Upewnij się, że nadawca i odbiorca mają zezwolenie na wysyłanie i odbieranie wiadomości e-mail z nieznanych źródeł (źródeł zewnętrznych) na koncie e-mail.
źródło
msg
nie jest prawidłową wiadomością SMTP i po prostu zniknie w eterze, jeśli Twój serwer pocztowy ją zaakceptuje.Pomyślałem, że umieściłem tutaj moje dwa bity, ponieważ właśnie zorientowałem się, jak to działa.
Wygląda na to, że nie masz portu określonego w ustawieniach połączenia SERWERA, co trochę mnie wywarło, gdy próbowałem połączyć się z moim serwerem SMTP, który nie używa domyślnego portu: 25.
Zgodnie z dokumentacją smtplib.SMTP, żądanie / odpowiedź ehlo lub helo powinno być automatycznie obsługiwane, więc nie powinieneś się tym martwić (ale może być coś do potwierdzenia, jeśli wszystko inne zawiedzie).
Inną kwestią, którą należy sobie zadać, jest to, czy zezwoliłeś na połączenia SMTP na samym serwerze SMTP? W przypadku niektórych witryn, takich jak GMAIL i ZOHO, musisz faktycznie wejść i aktywować połączenia IMAP na koncie e-mail. Być może Twój serwer pocztowy nie zezwala na połączenia SMTP, które nie pochodzą z „localhost”? Coś, na co warto zwrócić uwagę.
Ostatnią rzeczą jest to, że możesz spróbować zainicjować połączenie w TLS. Większość serwerów wymaga teraz tego typu uwierzytelniania.
Zobaczysz, że umieściłem dwa pola TO w moim e-mailu. Elementy słownika msg ['DO'] i msg ['FROM'] msg umożliwiają wyświetlanie poprawnych informacji w nagłówkach wiadomości e-mail, które można zobaczyć na końcu wiadomości e-mail w polach Do / Od (Ty może nawet uda się dodać tutaj pole Odpowiedz do. Same pola DO i OD są tym, czego wymaga serwer.Wiem, że słyszałem o niektórych serwerach pocztowych odrzucających wiadomości e-mail, jeśli nie mają odpowiednich nagłówków wiadomości e-mail.
Oto kod, którego użyłem w funkcji, która działa dla mnie, aby wysłać e-mailem zawartość pliku * .txt przy użyciu mojego lokalnego komputera i zdalnego serwera SMTP (ZOHO, jak pokazano):
źródło
Warto zauważyć, że moduł SMTP obsługuje menedżera kontekstu, więc nie ma potrzeby ręcznego wywoływania quit (), co gwarantuje, że jest wywoływany zawsze, nawet jeśli jest wyjątek.
źródło
Jeśli chodzi o twój kod, wydaje się, że nie ma w nim nic zasadniczo złego, poza tym, że nie jest jasne, w jaki sposób faktycznie wywołujesz tę funkcję. Wszystko, o czym mogę pomyśleć, to to, że gdy twój serwer nie odpowiada, otrzymasz ten błąd SMTPServerDisconnected. Jeśli spojrzysz na funkcję getreply () w smtplib (fragment poniżej), zobaczysz pomysł.
sprawdź przykład na https://github.com/rreddy80/sendEmails/blob/master/sendEmailAttachments.py, który również używa wywołania funkcji do wysyłania wiadomości e-mail, jeśli to jest to, co próbujesz zrobić (podejście DRY).
źródło