218

このコードは機能し、私にメールを送ってくれます。

import smtplib
#SERVER = "localhost"

FROM = 'monty@python.com'

TO = ["jon@mycompany.com"] # 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()

ただし、次のような関数でラップしようとすると、次のようになります。

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

それを呼び出すと、次のエラーが発生します。

 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

誰かが私に理由を理解するのを手伝ってもらえますか?

4

14 に答える 14

223

標準パッケージemailsmtplib一緒に使用してメールを送信することをお勧めします。次の例を見てください(Pythonのドキュメントから複製)。このアプローチに従うと、「単純な」タスクは確かに単純であり、より複雑なタスク(バイナリオブジェクトのアタッチやプレーン/ HTMLマルチパートメッセージの送信など)は非常に迅速に実行されることに注意してください。

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

複数の宛先に電子メールを送信する場合は、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()

ご覧のとおりToMIMETextオブジェクトのヘッダーは、コンマで区切られた電子メールアドレスで構成される文字列である必要があります。一方、sendmail関数の2番目の引数は文字列のリストである必要があります(各文字列は電子メールアドレスです)。

したがって、、、、の3つの電子メールアドレスがある場合は、次person1@example.comのようperson2@example.comperson3@example.com実行できます(明らかなセクションは省略されています)。

to = ["person1@example.com", "person2@example.com", "person3@example.com"]
msg['To'] = ",".join(to)
s.sendmail(me, to, msg.as_string())

パーツは、",".join(to)リストからコンマで区切られた単一の文字列を作成します。

あなたの質問から、あなたはPythonチュートリアルを経験していないことがわかります-Pythonのどこかに行きたいのなら、それは必須です-ドキュメントは標準ライブラリにとってほとんど優れています。

于 2011-06-07T20:07:33.873 に答える
87

Pythonでメールを送信する必要がある場合は、メールを整理して送信する際に多くの問題を抱えるmailgunAPIを使用します。彼らはあなたが月に5,000の無料の電子メールを送ることを可能にする素晴らしいアプリ/APIを持っています。

メールの送信は次のようになります。

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 <mailgun@YOUR_DOMAIN_NAME>",
              "to": ["bar@example.com", "YOU@YOUR_DOMAIN_NAME"],
              "subject": "Hello",
              "text": "Testing some Mailgun awesomness!"})

イベントなどを追跡することもできます。クイックスタートガイドを参照してください

于 2016-02-09T16:16:14.457 に答える
58

yagmailパッケージにアドバイスしてメールの送信をお手伝いしたいと思います(私はメンテナです。広告は申し訳ありませんが、本当に役立つと思います!)。

コード全体は次のようになります。

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

すべての引数にデフォルトを提供していることに注意してください。たとえば、自分自身に送信する場合は省略できTOます。件名が不要な場合は省略できます。

さらに、HTMLコードや画像(およびその他のファイル)を簡単に添付できるようにすることも目標です。

コンテンツを配置する場所では、次のようなことができます。

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']

うわー、添付ファイルを送信するのはとても簡単です!これはyagmailなしで20行のようになります;)

また、一度設定すれば、パスワードを再度入力する必要はありません(そして安全に保管しておく必要があります)。あなたの場合、あなたは次のようなことをすることができます:

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

これははるかに簡潔です!

githubをご覧になるか、を使用して直接インストールすることをお勧めしますpip install yagmail

于 2015-12-07T17:44:36.563 に答える
17

インデントの問題があります。以下のコードは機能します:

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

于 2015-08-12T06:21:41.007 に答える
14

これはPythonの例で3.x、以下よりもはるかに単純です2.x

import smtplib
from email.message import EmailMessage
def send_mail(to_email, subject, message, server='smtp.example.cn',
              from_email='xx@example.com'):
    # 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.')

この関数を呼び出します。

send_mail(to_email=['12345@qq.com', '12345@126.com'],
          subject='hello', message='Your analysis has done!')

以下は中国のユーザーのみが対象です。

126/163、0042易邮箱を使用する場合は、以下のように「客户端授許可密码」を設定する必要があります。

ここに画像の説明を入力してください

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

于 2017-11-30T10:59:21.220 に答える
5

関数でコードをインデントしている間(これは問題ありません)、生のメッセージ文字列の行もインデントしました。ただし、先頭の空白は、RFC 2822のセクション2.2.3および3.2.3で説明されているように、ヘッダー行の折りたたみ(連結)を意味します-インターネットメッセージ形式

各ヘッダーフィールドは、論理的には、フィールド名、コロン、およびフィールド本体を構成する1行の文字です。ただし、便宜上、および1行あたりの998/78文字の制限に対処するために、ヘッダーフィールドのフィールド本体部分を複数行の表現に分割できます。これは「折りたたみ」と呼ばれます。

呼び出しの関数形式ではsendmail、すべての行が空白で始まっているため、「展開」(連結)されて送信しようとしています

From: monty@python.com    To: jon@mycompany.com    Subject: Hello!    This message was sent with Python's smtplib.

これらの名前は行の先頭でのみ認識されるため、私たちの心が示唆する以外は、ヘッダーとヘッダーsmtplibを理解できなくなります。代わりに、非常に長い送信者の電子メールアドレスを想定します。To:Subject:smtplib

monty@python.com    To: jon@mycompany.com    Subject: Hello!    This message was sent with Python's smtplib.

これは機能しないため、例外が発生します。

解決策は簡単ですmessage。以前と同じように文字列を保持するだけです。これは、関数(Zeeshanが提案したように)によって、またはソースコードですぐに実行できます。

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

これで展開は発生せず、送信します

From: monty@python.com
To: jon@mycompany.com
Subject: Hello!

This message was sent with Python's smtplib.

これが機能し、古いコードによって実行されたものです。

また、RFCのセクション3.5(必須)に対応するためにヘッダーと本文の間の空の行を保持し、PythonスタイルガイドPEP-0008(オプション)に従って関数の外にインクルードを配置していることに注意してください。

于 2016-02-08T05:38:33.063 に答える
3

それはおそらくあなたのメッセージにタブを入れているでしょう。sendMailに渡す前に、メッセージを印刷してください。

于 2011-06-07T19:52:47.047 に答える
2

送信者と受信者の両方が電子メールを送信し、電子メールアカウントの不明なソース(外部ソース)から電子メールを受信することを許可していることを確認してください。

import smtplib

#Ports 465 and 587 are intended for email client to email server communication - sending email
server = smtplib.SMTP('smtp.gmail.com', 587)

#starttls() is a way to take an existing insecure connection and upgrade it to a secure connection using SSL/TLS.
server.starttls()

#Next, log in to the server
server.login("#email", "#password")

msg = "Hello! This Message was sent by the help of Python"

#Send the mail
server.sendmail("#Sender", "#Reciever", msg)

ここに画像の説明を入力してください

于 2018-12-29T14:51:29.173 に答える
1

これがどのように機能するかを理解したばかりなので、ここに2つのビットを入れたいと思いました。

サーバー接続設定でポートが指定されていないようです。これは、デフォルトのポート25を使用していないSMTPサーバーに接続しようとしたときに少し影響を受けました。

smtplib.SMTPのドキュメントによると、ehloまたはheloの要求/応答は自動的に処理されるため、これについて心配する必要はありません(ただし、他のすべてが失敗したかどうかを確認するためのものである可能性があります)。

もう1つ自問することは、SMTPサーバー自体でSMTP接続を許可したかどうかです。GMAILやZOHOなどの一部のサイトでは、実際にアクセスして、メールアカウント内でIMAP接続をアクティブ化する必要があります。あなたのメールサーバーはおそらく「localhost」から来ていないSMTP接続を許可しないかもしれませんか?調べるべき何か。

最後に、TLSで接続を開始してみてください。現在、ほとんどのサーバーでこのタイプの認証が必要です。

2つのTOフィールドをメールに詰め込んだことがわかります。msg['TO']およびmsg['FROM']msgディクショナリ項目を使用すると、電子メール自体のヘッダーに正しい情報を表示できます。この情報は、電子メールの受信側の[宛先] /[送信元]フィールドに表示されます(ここに返信先フィールドを追加できる場合もあります。TOフィールドとFROMフィールド自体がサーバーに必要なものです。適切なメールヘッダーがない場合、一部のメールサーバーがメールを拒否するという話を聞いたことがあります。

これは、関数で使用したコードで、ローカルコンピューターとリモートSMTPサーバー(図のようにZOHO)を使用して*.txtファイルのコンテンツを電子メールで送信するために機能します。

def emailResults(folder, filename):

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

    # headers
    TO = 'to_user@domain.com'
    msg['To'] = TO
    FROM = 'from_user@domain.com'
    msg['From'] = FROM
    msg['Subject'] = 'email subject |' + filename

    # SMTP
    send = smtplib.SMTP('smtp.zoho.com', 587)
    send.starttls()
    send.login('from_user@domain.com', 'password')
    send.sendmail(FROM, TO, msg.as_string())
    send.quit()
于 2016-06-10T23:10:28.367 に答える
0

SMTPモジュールはコンテキストマネージャーをサポートしているため、手動でquit()を呼び出す必要はありません。これにより、例外が発生した場合でも常に呼び出されることが保証されます。

    with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
        server.ehlo()
        server.login(user, password)
        server.sendmail(from, to, body)
于 2020-07-03T10:56:01.230 に答える
0
import smtplib, ssl

port = 587  # For starttls
smtp_server = "smtp.office365.com"
sender_email = "170111018@student.mit.edu.tr"
receiver_email = "professordave@hotmail.com"
password = "12345678"
message = """\
Subject: Final exam

Teacher when is the final exam?"""

def SendMailf():
    context = ssl.create_default_context()
    with smtplib.SMTP(smtp_server, port) as server:
        server.ehlo()  # Can be omitted
        server.starttls(context=context)
        server.ehlo()  # Can be omitted
        server.login(sender_email, password)
        server.sendmail(sender_email, receiver_email, message)
        print("mail send")
于 2021-09-24T09:27:26.780 に答える
0

Gmailを使用した別の実装は次のようにしましょう:

import smtplib

def send_email(email_address: str, subject: str, body: str):
"""
send_email sends an email to the email address specified in the
argument.

Parameters
----------
email_address: email address of the recipient
subject: subject of the email
body: body of the email
"""

server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login("email_address", "password")
server.sendmail("email_address", email_address,
                "Subject: {}\n\n{}".format(subject, body))
server.quit()
于 2021-12-22T09:52:04.197 に答える
0

メールを送信するためのパッケージオプションに満足していないので、自分のメール送信者を作成してオープンソースにすることにしました。使いやすく、高度なユースケースに対応できます。

インストールするには:

pip install redmail

使用法:

from redmail import EmailSender
email = EmailSender(
    host="<SMTP HOST ADDRESS>",
    port=<PORT NUMBER>,
)

email.send(
    sender="me@example.com",
    receivers=["you@example.com"],
    subject="An example email",
    text="Hi, this is text body.",
    html="<h1>Hi,</h1><p>this is HTML body</p>"
)

サーバーでユーザーとパスワードが必要な場合は、user_namepasswordをに渡すだけEmailSenderです。

メソッドにラップされた多くの機能を含めましたsend

  • 添付ファイルを含める
  • HTML本文に直接画像を含める
  • ジンジャテンプレート
  • 箱から出してすぐにきれいなHTMLテーブル

ドキュメント: https ://red-mail.readthedocs.io/en/latest/

ソースコード:https ://github.com/Miksus/red-mail

于 2022-01-01T19:38:55.390 に答える
-1

コードに関する限り、その関数を実際にどのように呼び出しているかが不明であることを除いて、根本的に問題はないようです。私が考えることができるのは、サーバーが応答していないときに、このSMTPServerDisconnectedエラーが発生するということだけです。smtplib(以下の抜粋)でgetreply()関数を検索すると、アイデアが得られます。

def getreply(self):
    """Get a reply from the server.

    Returns a tuple consisting of:

      - server response code (e.g. '250', or such, if all goes well)
        Note: returns -1 if it can't read response code.

      - server response string corresponding to response code (multiline
        responses are converted to a single, multiline string).

    Raises SMTPServerDisconnected if end-of-file is reached.
    """

https://github.com/rreddy80/sendEmails/blob/master/sendEmailAttachments.pyで例を確認してください。この例では、関数呼び出しを使用して電子メールを送信します(これが目的の場合)(DRYアプローチ)。

于 2016-02-12T11:48:49.220 に答える