【问题标题】:Receive and send emails in python在 python 中接收和发送电子邮件
【发布时间】:2010-09-25 19:00:07
【问题描述】:

如何在 python 中接收和发送电子邮件?某种“邮件服务器”。

我正在研究制作一个应用程序,它会监听它是否接收到发往 foo@bar.domain.com 的电子邮件,并向发件人发送电子邮件。

现在,我可以在 python 中完成这一切吗,最好使用 3rd 方库吗?

【问题讨论】:

    标签: python email


    【解决方案1】:

    这是一个非常简单的例子:

    import smtplib
    
    server = 'mail.server.com'
    user = ''
    password = ''
    
    recipients = ['user@mail.com', 'other@mail.com']
    sender = 'you@mail.com'
    message = 'Hello World'
    
    session = smtplib.SMTP(server)
    # if your SMTP server doesn't need authentications,
    # you don't need the following line:
    session.login(user, password)
    session.sendmail(sender, recipients, message)
    

    有关更多选项、错误处理等,请查看smtplib module documentation

    【讨论】:

    • 这涵盖了发送部分,如果您可以添加一个快速的 sn-p 以使用 smptd 模块收听新邮件,这将是一个很好的答案
    • 请注意,这与真正的电子邮件服务器相差甚远,因为大部分实际工作(排队和重新传输)是由“mail.server.com”完成的,而不是由 Python 程序完成的。
    • 令人难以置信的这个答案得到了这么多的赞成,因为它不到一半的答案。
    • 它显然只是这里回答的问题的一半
    • 你从来没有回答过如何接收电子邮件。
    【解决方案2】:

    找到了一个通过使用 IMAP 连接来阅读电子邮件的有用示例:

    Python — imaplib IMAP example with Gmail

    import imaplib
    mail = imaplib.IMAP4_SSL('imap.gmail.com')
    mail.login('myusername@gmail.com', 'mypassword')
    mail.list()
    # Out: list of "folders" aka labels in gmail.
    mail.select("inbox") # connect to inbox.
    result, data = mail.search(None, "ALL")
    
    ids = data[0] # data is a list.
    id_list = ids.split() # ids is a space separated string
    latest_email_id = id_list[-1] # get the latest
    
    # fetch the email body (RFC822) for the given ID
    result, data = mail.fetch(latest_email_id, "(RFC822)") 
    
    raw_email = data[0][1] # here's the body, which is raw text of the whole email
    # including headers and alternate payloads
    

    【讨论】:

    • 感谢您的链接,这是一个很好的资源。 IMAP4 比 POP3 更先进,但提供了更多功能,例如能够搜索标题。
    【解决方案3】:

    我认为用 Python 编写一个真正的邮件服务器不是一个好主意。这当然是可能的(有关详细信息,请参阅 mcrute 和 Manuel Ceron 的帖子),但是当您想到真正的邮件服务器必须处理的所有事情(排队、重新传输、处理垃圾邮件等)时,工作量很大。

    您应该更详细地说明您需要什么。如果您只想对收到的电子邮件做出反应,我建议将邮件服务器配置为在收到电子邮件时调用程序。这个程序可以做它想做的事情(更新数据库、创建文件、与另一个 Python 程序对话)。

    要从邮件服务器调用任意程序,您有多种选择:

    1. 对于 sendmail 和 Postfix,~/.forward 包含 "|/path/to/program"
    2. 如果您使用 procmail,|path/to/program 的配方操作
    3. 当然还有很多其他人

    【讨论】:

    • 我讨厌人们在不添加评论的情况下投反对票。我的回答有什么问题?
    • 我不知道会是什么问题。这基本上是我的答案,有更多细节。我认为这是一个很好的解决方案。
    • 其实python的smtpd服务器对于我用过的内部应用来说还是很不错的。正确使用 SMTP 确实不是那么难,难的部分是多路复用网络连接。我不确定我会用它来处理“真实”的生产负载。
    • 感谢您的详细解答!同样的概念也适用于 Windows 服务器,使用 IIS 的本地 SMTP 虚拟服务器。
    【解决方案4】:

    Python 有一个 SMTPD 模块,可以帮助您编写服务器。您可能还希望 SMTP 模块进行重新发送。至少从 2.3 版开始,这两个模块都在标准库中。

    【讨论】:

      【解决方案5】:

      poplib 和 smtplib 将成为您开发应用程序时的朋友。

      【讨论】:

        【解决方案6】:

        发送部分已覆盖,接收可以使用popimap

        【讨论】:

          【解决方案7】:

          根据您发送的邮件数量,您可能需要考虑使用真正的邮件服务器,如 postifx 或 sendmail(*nix 系统)这两个程序都能够将收到的邮件发送到基于电子邮件地址。

          【讨论】:

            【解决方案8】:

            最好的方法是在 python 中创建一个 Windows 服务,使用 imaplib2 接收电子邮件

            以下是执行相同操作的示例 python 脚本。您可以通过在命令行“python THENAMEOFYOURSCRIPTFILE.py install”上运行以下命令来安装此脚本以作为 Windows 服务运行。

            import win32service
            import win32event
            import servicemanager
            import socket
            import imaplib2, time
            from threading import *
            import smtplib
            from email.MIMEMultipart import MIMEMultipart
            from email.MIMEText import MIMEText
            import datetime
            import email
            
            class Idler(object):
                def __init__(self, conn):
                    self.thread = Thread(target=self.idle)
                    self.M = conn
                    self.event = Event()
            
                def start(self):
                    self.thread.start()
            
                def stop(self):
                    self.event.set()
            
                def join(self):
                    self.thread.join()
            
                def idle(self):
                    while True:
                        if self.event.isSet():
                            return
                        self.needsync = False
                        def callback(args):
                            if not self.event.isSet():
                                self.needsync = True
                                self.event.set()
                        self.M.idle(callback=callback)
                        self.event.wait()
                        if self.needsync:
                            self.event.clear()
                            self.dosync()
            
            
                def dosync(self):
                    #DO SOMETHING HERE WHEN YOU RECEIVE YOUR EMAIL
            
            class AppServerSvc (win32serviceutil.ServiceFramework):
                _svc_name_ = "receiveemail"
                _svc_display_name_ = "receiveemail"
            
            
                def __init__(self,args):
                    win32serviceutil.ServiceFramework.__init__(self,args)
                    self.hWaitStop = win32event.CreateEvent(None,0,0,None)
                    socket.setdefaulttimeout(60)
            
                def SvcStop(self):
                    self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
                    win32event.SetEvent(self.hWaitStop)
            
                def SvcDoRun(self):
                    servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                                          servicemanager.PYS_SERVICE_STARTED,
                                          (self._svc_name_,''))
                    self.main()
            
                def main(self):
                    M = imaplib2.IMAP4_SSL("imap.gmail.com", 993)
                    M.login("YourID", "password")
                    M.select("INBOX")
                    idler = Idler(M)
                    idler.start()
                    while True:
                        time.sleep(1*60)
                    idler.stop()
                    idler.join()
                    M.close()
                    M.logout()
            
            if __name__ == '__main__':
                win32serviceutil.HandleCommandLine(AppServerSvc)
            

            【讨论】:

            • 这在我看来是不必要的复杂。通过将此作为 Windows 服务而不是仅仅将其保留为(独立于平台的)线程或进程,您可以获得什么?
            • @Wallacoloo。我写这篇文章时考虑到了 Windows 操作系统。永远运行的东西最好作为 Windows 服务运行。服务的好处绝对值得增加的复杂性。我的拙见。
            【解决方案9】:

            您可以使用emailpy

            通过pip3 install emailpy安装

            import emailpy
            manager = emailpy.EmailManager('your email', 'your password')
            msg = manager.send(['who you are sending to', 'the other email you are sending to', subject='hello', body='this email is sent from Python', html='<h1>Hello World!</h1>', attachments=['yourfile.txt', 'yourotherfile.py'])
            while not msg.sent:
                pass
            print('sent')
            messages = manager.read()
            for message in messages:
                print(message.sender, message.date, message.subject, message.body, message.html, message.attachments)
                for attachment in message.attachments:
                    print(attachment.name)
                    attachment.download()
            

            【讨论】:

              猜你喜欢
              • 2017-04-27
              • 2010-10-18
              • 1970-01-01
              • 2019-03-04
              • 2014-04-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-01-09
              相关资源
              最近更新 更多