Python3 socket.gaierror 然后调用 smtplib.SMTP
Python3 socket.gaierror then calling smtplib.SMTP
问题描述
我在 sendmail.py 中实现了通过 smtplib 发送电子邮件的功能。
在 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
,所以这不是连接/网络问题。
Note: I have installed latest python via pyenv, so /usr/bin/env python3 runs it. Python/iPython runs same version of 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()
经过一些研究,我找到了问题的解决方案:问题发生了,因为我在系统 python 版本旁边通过 pyenv 安装了最新的 python 版本。
看起来 python 与系统一起安装可以访问低级系统接口,例如套接字,然后新安装的 python 没有。
所以问题解决了,然后我运行我的代码与系统python(版本3.4.2)。
问题描述
我在 sendmail.py 中实现了通过 smtplib 发送电子邮件的功能。
在 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
,所以这不是连接/网络问题。
Note: I have installed latest python via pyenv, so /usr/bin/env python3 runs it. Python/iPython runs same version of 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()
经过一些研究,我找到了问题的解决方案:问题发生了,因为我在系统 python 版本旁边通过 pyenv 安装了最新的 python 版本。 看起来 python 与系统一起安装可以访问低级系统接口,例如套接字,然后新安装的 python 没有。 所以问题解决了,然后我运行我的代码与系统python(版本3.4.2)。