【问题标题】:Sending email with smtplib, no errors but no messages delivered使用 smtplib 发送电子邮件,没有错误但没有消息传递
【发布时间】:2020-01-04 11:27:01
【问题描述】:

**UPDATE2:在 V2 的最后一段代码中,我将 smtp.sendmail(email_address, address, msg,)smtp.sendmail(email_address, phone_book, msg,) 交换了直接访问 phone_book 似乎已经解决了这个问题。这是任何正在寻找的人的工作代码:

import smtplib

email_address = '' # Your email goes here
email_password = '' # Your password goes here
phone_book = [''] # List of receivers


def Add_Email():
    client_email = input('Email of receiver? ')
    phone_book.append(client_email)

def Add_Subject_Message_Send():    
    with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
            smtp.ehlo()
            smtp.starttls()
            smtp.ehlo()

            smtp.login(email_address, email_password)

            subject = input('Enter your subject here: ')
            body = input('Enter your message here: ')

            msg = f'Subject: {subject}\n\n{body}'

            for i in phone_book:
                address = i
                smtp.sendmail(email_address, phone_book, msg,)


Add_Email()
Add_Subject_Message_Send()

**

**更新:我用最简单的没有 GUI 的版本交换了代码。当主题和主体在代码中定义时,V1 工作。当用户定义主题和正文时,V2 不起作用。现在 V2 有这个错误信息:

Traceback (most recent call last):
  File "c:/Users/Me/Desktop/work/infosend/test4.py", line 33, in <module>
    Add_Subject_Message_Send()
  File "c:/Users/Me/Desktop/work/infosend/test4.py", line 29, in Add_Subject_Message_Send
    smtp.sendmail(email_address, address, msg,)
  File "C:\python\lib\smtplib.py", line 885, in sendmail
    raise SMTPRecipientsRefused(senderrs)
smtplib.SMTPRecipientsRefused: {'': (555, b'5.5.2 Syntax error. l15sm65056407wrv.39 - gsmtp')}

**

我正在使用 smtplib 发送电子邮件。只要在代码中定义了消息的主题和正文,一切都会正常工作并且电子邮件会被传递。当代码中没有定义主题或正文时,不会显示错误,但不会传递消息。

我想创建一个函数,让我可以写出主题和消息是什么,而不是在代码中定义它。我的功能似乎可以工作,但没有传递任何消息,也没有收到错误消息。

附上我的代码的两个版本。

第一个版本有效。它定义了主题和主体。

第二个版本不起作用。包括定义主题和主体的功能。终端没有收到错误。

V1

import smtplib

email_address = '' # Enter your email address here
email_password = '' # Enter your email password here

phone_book = [''] # Here enter the email of receiver

with smtplib.SMTP('smtp.gmail.com', 587) as smtp: # Connects with GMAIL
            smtp.ehlo()
            smtp.starttls()
            smtp.ehlo()

            smtp.login(email_address, email_password)

            subject = 'test3' # Subject and body defined in code = works
            body = 'test3'

            msg = f'Subject: {subject}\n\n{body}'

            for i in phone_book:
                address = i
                smtp.sendmail(email_address, address, msg,)

V2

    import smtplib

email_address = '' # Your email goes here
email_password = '' # Your password goes here
phone_book = [''] # List of receivers


def Add_Email():
    client_email = input('Email of receiver? ')
    phone_book.append(client_email)

def Add_Subject_Message_Send():    
    with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
            smtp.ehlo()
            smtp.starttls()
            smtp.ehlo()

            smtp.login(email_address, email_password)

            subject = input('Enter your subject here: ')
            body = input('Enter your message here: ')

            msg = f'Subject: {subject}\n\n{body}'

            for i in phone_book:
                address = i
                smtp.sendmail(email_address, address, msg,)


Add_Email()
Add_Subject_Message_Send()

【问题讨论】:

  • 你真的应该把它减少到minimal reproducible example。 GUI 代码完全是多余的,与您的问题无关,这使得其他人更难以审查和测试。
  • 这两者都有缺陷,因为简单地连接两个变量并不是构造有效 RFC822 电子邮件的正确方法。它适用于简单的英文短字符串,但不适用于更多有趣的字符串。事实上,您的代码在 v2 代码中硬编码了一个空主体,所以它当然会失败,正如您在问题描述中预测的那样。
  • 能否将您的代码引用减少到仅使用您的电子邮件发送方式?
  • @Irfanuddin 很抱歉造成混乱。我尽可能地减少了代码并在帖子中进行了更新。
  • 您提到使用 PySimpleGUI。您是否查看过为发送电子邮件而发布的演示程序?它显示了一个 GUI 以及它如何与 smtplib 一起使用以成功发送电子邮件 - github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/…

标签: python smtplib pysimplegui


【解决方案1】:

我无法重现您声称从早期版本的代码中得到的语法错误。但是,您的尝试还有其他一些问题。

首先,要解决问题,请尝试添加

smtp.set_debuglevel(1)

准确显示您发送的内容。理解生成的成绩单需要了解 SMTP,但如果您将来有类似的问题,包括此成绩单可能会很有价值。

其次,像这样在循环中重复发送相同的消息是有问题的 - 这很浪费,并且可能会触发自动反垃圾邮件控制。要将相同的消息发送给多个收件人,只需在调用sendmail 时列出所有收件人(这基本上将他们作为Bcc: 收件人)。

第三,对于电子邮件的外观,您确实有一个过于简单的模型。如果这两个部分都是普通的 ASCII 字符串,则只有 Subject: 和简单文本正文的最小消息是有效的,但现代电子邮件消息在不是这种情况时需要编码(例如 Unicode 字符串或二进制附件)。当然,您可以自己拼凑一条有效的消息,但这很乏味;您应该改用 Python email 库。

这是来自the documentation.的简短改编

import smtplib
from email.message import EmailMessage

msg = EmailMessage()
msg['From'] = email_address
msg['To'] = ', '.join(phone_book)
msg['Subject'] = subject
msg.set_content(body)

with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
    smtp.ehlo()
    smtp.starttls()
    smtp.ehlo()

    smtp.login(email_address, email_password)

    smtp.send_message(msg)
    smtp.quit()

有许多旧示例使用旧的 email.message.Message 类,但现在应该避免这些。大修的email 库在 Python 3.3 中引入,并成为 3.5 的官方推荐版本。

【讨论】:

    【解决方案2】:

    请参考我的代码。我已经做到了,它正在工作。 您可以通过参考我的代码获得一些线索。

    查看main功能码。

    import smtplib
    
    from string import Template
    
    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    
    MY_ADDRESS = 'xyz@gmail.com'
    PASSWORD = 'YourPassword'
    
    
    def get_contacts(filename):
        names = []
        emails = []
        with open(filename, mode='r', encoding='utf-8') as contacts_file:
            for a_contact in contacts_file:
                names.append(a_contact.split()[0])
                emails.append(a_contact.split()[1])
        return names, emails
    
    
    def read_template(filename):
        with open(filename, 'r', encoding='utf-8') as template_file:
            template_file_content = template_file.read()
        return Template(template_file_content)
    
    
    def main():
        names, emails = get_contacts('C:/Users/VAIBHAV/Desktop/mycontacts.txt')  # read contacts
        message_template = read_template('C:/Users/VAIBHAV/Desktop/message.txt')
        s = smtplib.SMTP(host='smtp.gmail.com', port=587)
        s.starttls()
        s.login(MY_ADDRESS, PASSWORD)
        for name, email in zip(names, emails):
            msg = MIMEMultipart()  # create a message
            message = message_template.substitute(PERSON_NAME=name.title())
            print(message)
            msg['From'] = MY_ADDRESS
            msg['To'] = email
            msg['Subject'] = "Sending mail to all"
            msg.attach(MIMEText(message, 'plain'))
            s.send_message(msg)
            del msg
        s.quit()
    if __name__ == '__main__':
        main()
    

    【讨论】:

    • @SPersonDPerson 查看我的解决方案
    • 再次感谢您提供的所有知识。在这一点上,我认为我没有足够的知识和经验能够在没有人逐行向我解释的情况下理解你的答案,但我真的很感激,我会在继续学习的过程中继续参考它。谢谢!
    • @SPersonDPerson 一定会尝试逐行向您解释我的代码...?
    【解决方案3】:

    而不是: 地址 = phone_book

    尝试使用: 地址 = 我

    我认为问题可能是您将地址变量设置为列表而不是列表中的单个项目。

    【讨论】:

    • 我将代码换成了一个简单的版本,因为另一个版本不可读。我按照您在该代码中的建议使用了 address = i ,但它没有改变任何东西。
    猜你喜欢
    • 2021-06-19
    • 2014-01-31
    • 2021-09-26
    • 1970-01-01
    • 1970-01-01
    • 2018-05-16
    • 1970-01-01
    • 2014-01-14
    • 1970-01-01
    相关资源
    最近更新 更多