间歇性 smtp 管道损坏 (errno 32)

发布于 2024-10-01 03:39:17 字数 2616 浏览 0 评论 0原文

我有一个 python 脚本,它全天定期使用 smtplib 发送几组电子邮件(发送到具有不同内容的不同地址)。有时(例如,当同时发送多批电子邮件时,大约五分之一),我会收到 IOError(errno:管道损坏)。我尝试重置并退出 SMTP 服务器,然后再次连接到服务器并尝试重新发送,但如果第一次失败,则总是会失败(有相同的例外)。 SMTP 服务器由学院维护,应该是可靠的(只要您在 Intranet 上,就允许免登录电子邮件)。

忽略下面代码的丑陋(缺乏 DRY),任何人都可以建议一种更可靠的连接方式吗?

我创建一个名为 EmailSet 的类,它将发送一批包含成员函数 send_emails 的几封电子邮件:

class EmailSet(object):
    ...
    def send_emails(self):
        try: # Connect to server
            server = smtplib.SMTP( smtp_server_name_str, 25)
            server.set_debuglevel(self.verbose)
            server.ehlo()
            for email in self.email_set:
                try: # send 1st mail
                    logging.debug("Sending email to %r" % email.recipients)        
                    response_dict = server.sendmail(email.fromaddr, email.recipients, email.msg_str())
                    logging.info("Sent email to %r" % email.recipients)        
                except Exception as inst:
                    logging.error('RD: %r' % response_dict)
                    logging.error("Email Sending Failed")
                    logging.error("%r %s" % ( type(inst), inst ) )
                    try: # send second mail
                        logging.info("Second Attempt to send to %r" % email.recipients)
                        try:
                            server.rset() 
                            server.quit()
                        except:
                            pass
                        time.sleep(60) # wait 60s
                        server = smtplib.SMTP( smtp_server_name_str, 25)
                        server.set_debuglevel(self.verbose)
                        server.ehlo()
                        response_dict = server.sendmail(email.fromaddr, email.recipients, email.msg_str())
                        logging.info("Sent email to %r (2nd Attempt)" % email.recipients)        
                    except Exception as inst:
                        try:
                            logging.error('RD: %r' % response_dict)
                        except:
                            pass
                        logging.error("Second Attempt Email Sending Failed")
        except:
            logging.debug("Can't connect to server")
        finally:
            logging.debug("Reseting and Quitting Server")
            server.rset()
            server.quit()
            logging.debug("Successfully Quit Server")
        return True

关于如何继续调试这个问题有什么想法吗? stmp 服务器不是由我维护的,但应该维护良好(用于约 10k 人的组织)。我最初在发送每封电子邮件后连接并断开与 smtp 服务器的连接,但这产生的错误比此方法更多。

另外,使用 /usr/sbin/sendmail 而不是 smtplib 会更安全吗?

I have a python script that sends out a few sets of emails (to different addresses with different contents) using smtplib periodically throughout the day. Somewhat frequently (say about 1 in 5 times when sending out batches of more than one email at the same time), I get a IOError (errno: broken pipe). I try reseting and quitting the SMTP server and then connect to the server again and attempt to resend, but that always fails if it failed the first time (with the same exception). The SMTP server is maintained by the college and should be reliable (and allows loginless emails as long as you are on the intranet).

Ignoring the ugliness of the code below (lack of DRY), can anyone suggest a more reliable way to connect?

I create a class called EmailSet which will send a batch of a few emails that has a member function send_emails:

class EmailSet(object):
    ...
    def send_emails(self):
        try: # Connect to server
            server = smtplib.SMTP( smtp_server_name_str, 25)
            server.set_debuglevel(self.verbose)
            server.ehlo()
            for email in self.email_set:
                try: # send 1st mail
                    logging.debug("Sending email to %r" % email.recipients)        
                    response_dict = server.sendmail(email.fromaddr, email.recipients, email.msg_str())
                    logging.info("Sent email to %r" % email.recipients)        
                except Exception as inst:
                    logging.error('RD: %r' % response_dict)
                    logging.error("Email Sending Failed")
                    logging.error("%r %s" % ( type(inst), inst ) )
                    try: # send second mail
                        logging.info("Second Attempt to send to %r" % email.recipients)
                        try:
                            server.rset() 
                            server.quit()
                        except:
                            pass
                        time.sleep(60) # wait 60s
                        server = smtplib.SMTP( smtp_server_name_str, 25)
                        server.set_debuglevel(self.verbose)
                        server.ehlo()
                        response_dict = server.sendmail(email.fromaddr, email.recipients, email.msg_str())
                        logging.info("Sent email to %r (2nd Attempt)" % email.recipients)        
                    except Exception as inst:
                        try:
                            logging.error('RD: %r' % response_dict)
                        except:
                            pass
                        logging.error("Second Attempt Email Sending Failed")
        except:
            logging.debug("Can't connect to server")
        finally:
            logging.debug("Reseting and Quitting Server")
            server.rset()
            server.quit()
            logging.debug("Successfully Quit Server")
        return True

Any thoughts on how to proceed debugging this? The stmp server isn't maintained by me, though should be well-maintained (used for ~10k person organization). I originally connected and disconnected from the smtpserver after sending each email, but that produced more errors than this method.

Also would it be safer to use /usr/sbin/sendmail rather than smtplib?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

转角预定愛 2024-10-08 03:39:17

此外,使用 /usr/sbin/sendmail 而不是 smtplib 会更安全吗?

从处理消息队列和重试队列运行程序的角度来看。是的,sendmail 或其他本地 MTA 可以为您处理此问题。

关于如何继续调试这个问题有什么想法吗?

数据包捕获。使用wireshark捕获smtp流量,看看发生了什么。您有很多广泛的异常处理,但不一定会向您显示确切的错误。

Also would it be safer to use /usr/sbin/sendmail rather than smtplib?

From the point of view of handling a message queue and a queue-runner for retries. Yes, sendmail or another local MTA could handle this for you.

Any thoughts on how to proceed debugging this?

Packet capture. Use wireshark to capture the smtp traffic, see whats going on. You've got a lot of broad exception handling that isn't necessarily showing you the exact error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文