Python3 socket.gaierror然后调用smtplib.SMTP

时间:2017-06-25 18:52:14

标签: python sockets email python-3.6 smtplib

问题描述

我已经实现了通过smtplib在 sendmail.py 中发送电子邮件的功能。 在 main.py 中,我导入了sendmail并使用它。然后我运行main.py,它在s = smtplib.SMTP(SMTP_SERVER)上崩溃了:

Traceback (most recent call last):
  File "./main.py", line 30, in <module>
    main()
  File "./main.py", line 26, in main
    sendmail.send_email("alarm", images)
  File "/home/pi/src/alarm-system/new_meta/sendmail.py", line 76, in send_email
    s = smtplib.SMTP(SMTP_SERVER)
  File "/home/pi/.pyenv/versions/3.6.1/lib/python3.6/smtplib.py", line 251, in __init__
    (code, msg) = self.connect(host, port)
  File "/home/pi/.pyenv/versions/3.6.1/lib/python3.6/smtplib.py", line 335, in connect
    self.sock = self._get_socket(host, port, self.timeout)
  File "/home/pi/.pyenv/versions/3.6.1/lib/python3.6/smtplib.py", line 306, in _get_socket
    self.source_address)
  File "/home/pi/.pyenv/versions/3.6.1/lib/python3.6/socket.py", line 704, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
  File "/home/pi/.pyenv/versions/3.6.1/lib/python3.6/socket.py", line 743, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known

我是如何找到解决方案的

首先,我在交互式python3和ipython中检查我的sendmail模块(在部署代码的同一系统上)。 在交互式python / ipython中,它的工作方式就像魅力,电子邮件成功发送,没有错误的追溯:

pi at raspberrypi in ~/src/alarm-system/new_meta (master)
$ /usr/bin/env python3
Python 3.6.1 (default, Jun 22 2017, 22:14:56)
[GCC 4.9.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sendmail
>>> sendmail.send_email("alarm",[])
True
>>>

此外,我已检查系统如何解析smtp.gmail.com并使用telnet smtp.gmail.com 587,因此它不是连接/网络问题。

  

注意:我已经通过pyenv安装了最新的python,所以/ usr / bin / env python3运行它。 Python / iPython运行相同版本的python。

也许有人反击同样的问题?什么建议下一步调试?

代码

sendmail.py

#!/usr/bin/env python3
import smtplib
import mimetypes

from email import encoders
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.mime.base import MIMEBase

import logging

logger = logging.getLogger(__name__)

SMTP_SERVER = "smtp.gmail.com:587"

# Function to send email with attachments or not.
# NOTE: attachments (files variable) must be a list of paths to files
def send_email(subj=None,files=None):
    msg = MIMEMultipart()

    if subj == "log":
        subject = LOG_SUBJ
    else:
        subject = ALARM_SUBJ

    msg["Subject"] = subject
    msg["From"] = FROM_EMAIL
    msg["To"] = TO_EMAIL

    if files is not None and type(files) == list:
        for filename in files:
            content_type, encoding = mimetypes.guess_type(filename)
            if content_type is None or encoding is not None:
                content_type = "application/octet-stream"
            maintype, subtype = content_type.split("/", 1)

            if maintype == "text":
                with open(filename) as fp:
                    file_attach = MIMEText(fp.read(), _subtype=subtype)
                attach_name = filename.split("/")[-1]
                file_attach.add_header('Content-Disposition', 'attachment',
                               filename=attach_name)
                msg.attach(file_attach)
                logger.info("Text file detected and attached. File: %s",
                            filename)
            elif maintype == "image":
                with open(filename, "rb") as fp:
                    file_attach = MIMEImage(fp.read(), _subtype=subtype)
                attach_name = filename.split("/")[-1]
                file_attach.add_header('Content-Disposition', 'attachment',
                               filename=attach_name)
                msg.attach(file_attach)
                logger.info("Image file detected and attached. File: %s",
                            filename)
            else:
                with open(filename,"rb") as fp:
                    file_attach = MIMEBase(maintype, subtype)
                    file_attach.set_payload(fp.read())
                encoders.encode_base64(file_attach)

                msg.attach(file_attach)
                logger.info("Base64 file detected and attached. File: %s",
                            filename)
    elif files is None:
        msg += MIMEText("Alarm raised, no attachments files")


    composed = msg.as_string()
    s = smtplib.SMTP(SMTP_SERVER)

    s.starttls()

    try:
        s.login(USERNAME, PASSWORD)
        s.sendmail(FROM_EMAIL, TO_EMAIL, composed)
        logger.info("Email sended successfully.")
        logger.info("Email attachments: %s", files)
        s.close()
        return True
    except Exception as err:
        logger.error("Email not send! Error message: %s", err)
        s.close()
        return False

main.py

#!/usr/bin/env python3
import logging
from time import sleep

from gpiozero import MotionSensor
from datetime import datetime

import camera
import sendmail

logging.basicConfig(filename="/var/log/alarm/alarm.txt", level=logging.INFO,
                        format="%(asctime)s - %(levelname)s - %(funcName)s - %(message)s")

logger = logging.getLogger(__name__)


def main():

    pir = MotionSensor(7)
    #pir.when_motion() = alarmLogging()
    while True:
        if pir.motion_detected:
            logger.warning("MOTION DETECTED")
            images = camera.capture_image(2)
            logging.info("Send images to email: %s", images)
            sendmail.send_email("alarm", images)
            sleep(10)

if __name__ == '__main__':
main()

1 个答案:

答案 0 :(得分:0)

经过一番研究后我找到了问题的解决方案:出现了问题,因为我已经通过pyenv在系统python版本旁边安装了最新的python版本。 它看起来像安装系统的python可以访问低级系统接口,如套接字,然后新安装的python没有。 所以问题解决了,然后我用system python(版本3.4.2)运行我的代码。