SMTPRecipientsRefused 错误,python smtplib

问题描述 投票:0回答:1

我想制作一个脚本,使用 nxapi 读取我的 Nintendo Switch 好友列表,并在我的配置文件的“观看”部分中有人上线时向我发送电子邮件。我的网站由 DreamHost 托管。我在尝试发送测试电子邮件时不断收到 SMTPRecipientsRefused 错误。

剧本:

import json
import yaml
import os
import subprocess
import smtplib
import datetime
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import random

configpath = os.path.expanduser("~/.littlebitstudios/switchfriendwatch/configuration.yaml")

try:
  config = yaml.safe_load(open(configpath))
except FileNotFoundError:
  print("No configuration file! Create a file at", configpath, "and follow the format detailed on the project page.")
  exit()

# Setting up SMTP if email is enabled
mailsender = None
if config['email']['enabled'] == True:
  print("Email enabled.")
  print("Connecting to email server")
  try:
    mailsender = smtplib.SMTP(config['email']['server'], config['email']['port'])
    print("Logging in to email server")
    mailsender.login(config['email']['user'], config['email']['pass'])
    mailsender.ehlo_or_helo_if_needed()
    mailsender.starttls()
  except (smtplib.SMTPAuthenticationError, smtplib.SMTPConnectError, smtplib.SMTPException) as e:
    print(f"Error connecting to email server: {e}")
    exit()

# Gather NSO friend data from nxapi
nxapi = subprocess.run(["nxapi", "nso", "friends", "--json"], capture_output=True)
friends = None
if nxapi.returncode == 0:
  friends = json.loads(nxapi.stdout.decode("utf-8"))
else:
  print("Error running nxapi. Please check the tool and its installation.")


lastchecktime = datetime.datetime.fromisoformat(config['lastcheck'])
print("Last run time:",lastchecktime.strftime("%b %d, %Y at %I:%M %p"))

def mailsendonline(username, game, lastchange):
  message = MIMEMultipart()
  message['From'] = config['email']['sendfrom']
  message['To'] = config['email']['sendto']
  message['Subject'] = "Switch Friend Watch: " + username + " is online playing " + game

  # Create MIMEText object for the message body
  body_text = MIMEText("Your friend " + username + " is now online playing " + game + ". \nLast status update: " + lastchange.strftime("%b %d, %Y at %I:%M %p") + "." + "\n\nSwitch Friend Watch\na tool by LittleBit", 'plain')
  message.attach(body_text)

  # Send the email using the provided SMTP object (mailsender)
  mailsender.sendmail(config['email']['sendfrom'], config['email']['sendto'], message.as_string())

  # Optional: Print a success message
  print("Email sent successfully!")


# Checking for watched users online, and making sure their status has changed since the last time the script ran
for friend in friends:
    for watched in config['watched']:
        if datetime.datetime.fromtimestamp(friend['presence']['updatedAt']) > datetime.datetime.fromisoformat(config['lastcheck']):
          if watched['type']=="name":
            if friend['name']==watched['value']:
              if friend['presence']['state']=="ONLINE":
                print(friend['name'],"is watched and is online!")
                if config['email']['enabled']:
                  mailsendonline(friend['name'], friend['presence']['game']['name'], datetime.datetime.fromtimestamp(friend['presence']['updatedAt']))
              else:
                print(friend['name'],"is watched but isn't online.")
          elif watched['type']=="id":
            if friend['id']==watched['value']:
              if friend['presence']['state']=="ONLINE":
                print(friend['name'],"is watched and is online!")
              else:
                print(friend['name'],"is watched but isn't online.")
        else:
          print(friend['name'],"'s status hasn't changed since the script last ran, ignoring. Last change: ",datetime.datetime.fromtimestamp(friend['presence']['updatedAt']).strftime("%b %d, %Y at %I:%M %p"),sep="")
config['lastcheck'] = datetime.datetime.now().isoformat()

if config['email']['enabled']:
  if config['email']['sendtest']:
    print("Email enabled with sendtest flag set, sending a test email!")
    hashtagnumber=random.randint(1000,9999)
    mailsendonline("Player#"+str(hashtagnumber), "TestGame", datetime.datetime.now())
    config['email']['sendtest']=False

with open(configpath, 'w') as outfile:
    yaml.dump(config, outfile, default_flow_style=False)

我希望脚本能够顺利完成,并且我的收件箱中会出现一封电子邮件。

发生的事情是一个例外:

Traceback (most recent call last):
  File "/home/jaherron/code/python/switchfriendwatch.py", line 89, in <module>
    mailsendonline("Player#"+str(hashtagnumber), "TestGame", datetime.datetime.now())
  File "/home/jaherron/code/python/switchfriendwatch.py", line 57, in mailsendonline
    mailsender.sendmail(config['email']['sendfrom'], config['email']['sendto'], message.as_string())
  File "/usr/lib/python3.11/smtplib.py", line 901, in sendmail
    raise SMTPRecipientsRefused(senderrs)
smtplib.SMTPRecipientsRefused: {'[My personal email]': (554, b'5.7.1 <[My personal email]>: Recipient address rejected: Access denied')}
python smtplib
1个回答
0
投票

我通过使用普通的 SMTP 端口 465 解决了这个问题。Gmail 显然拒绝使用 STARTTLS 安全方法来接收电子邮件。

这是我的代码的最新版本。

import json
import yaml
import os
import subprocess
import smtplib
import datetime
import email
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import random

configpath = os.path.expanduser("~/.littlebitstudios/switchfriendwatch/configuration.yaml")

try:
  config = yaml.safe_load(open(configpath))
except FileNotFoundError:
  print("No configuration file! Create a file at", configpath, "and follow the format detailed on the project page.")
  exit()

# Setting up SMTP if email is enabled
mailsender = None
if config['email']['enabled'] == True:
  print("Email enabled.")
  print("Connecting to email server")
  try:
    mailsender = smtplib.SMTP_SSL(config['email']['server'], config['email']['port'])
    print("Logging in to email server")
    mailsender.set_debuglevel(config['email']['debugmode'])
    mailsender.login(config['email']['user'], config['email']['pass'])
    mailsender.ehlo_or_helo_if_needed()
  except (smtplib.SMTPAuthenticationError, smtplib.SMTPConnectError, smtplib.SMTPException) as e:
    print(f"Error connecting to email server: {e}")
    exit()

# Gather NSO friend data from nxapi
nxapi = subprocess.run(["nxapi", "nso", "friends", "--json"], capture_output=True)
friends = None
if nxapi.returncode == 0:
  friends = json.loads(nxapi.stdout.decode("utf-8"))
else:
  print("Error running nxapi. Please check the tool and its installation.")

def mailsendonline(username, game, lastchange):
  message = MIMEMultipart()
  message['From'] = "Switch Friend Watch"+" <"+config['email']['sendfrom']+">"
  message['To'] = config['email']['sendto']
  message['Subject'] = username+" is online playing "+game

  body_text = MIMEText("Your friend " + username + " is now online playing " + game + ". \nLast status update: " + lastchange.strftime("%b %d, %Y at %I:%M %p") + "." + "\n\nSwitch Friend Watch\na tool by LittleBit", 'plain')
  message.attach(body_text)

  try:
      mailsender.send_message(msg=message)
      print("Email sent successfully!")
  except smtplib.SMTPException as e:
      print(f"Error sending email: {e}")
      
def mailsendonlinewatched(username, game, lastchange):
  message = MIMEMultipart()
  message['From'] = "Switch Friend Watch"+" <"+config['email']['sendfrom']+">"
  message['To'] = config['email']['sendto']
  message['Subject'] ="[WATCHED] "+username+" is online playing "+game

  body_text = MIMEText(" Your friend " + username + " is now online playing " + game + ". \n You're watching this friend. \nLast status update: " + lastchange.strftime("%b %d, %Y at %I:%M %p") + "." + "\n\nSwitch Friend Watch\na tool by LittleBit", 'plain')
  message.attach(body_text)

  try:
      mailsender.send_message(msg=message)
      print("Email sent successfully!")
  except smtplib.SMTPException as e:
      print(f"Error sending email: {e}")
      
if config['email']['enabled']:
  if config['email']['sendtest']=="unwatched":
    print("Email enabled with sendtest flag set to unwatched, sending a test email for unwatched friend!")
    hashtagnumber=random.randint(1000,9999)
    mailsendonline("Player#"+str(hashtagnumber), "TestGame", datetime.datetime.now())
    config['email']['sendtest']="off"
    exit()
  if config['email']['sendtest']=="watched":
    print("Email enabled with sendtest flag set to watched, sending a test email for watched friend!")
    hashtagnumber=random.randint(1000,9999)
    mailsendonlinewatched("Player#"+str(hashtagnumber), "TestGame", datetime.datetime.now())
    config['email']['sendtest']="off"
    exit()
    
lastchecktime = datetime.datetime.fromisoformat(config['lastcheck'])
print("Last run time:",lastchecktime.strftime("%b %d, %Y at %I:%M %p"))

watched = list()
for user in config["watched"]:
  watched.append(user)

# Checking for watched users online, and making sure their status has changed since the last time the script ran
def check_and_send_email(user):
  last_check = datetime.datetime.fromisoformat(config['lastcheck'])
  updated_at = datetime.datetime.fromtimestamp(user['presence']['updatedAt'])

  if updated_at > last_check:
    is_online = user['presence']['state'] == "ONLINE"
    
    game_name = str()
    if is_online:
      game_name = user['presence']['game']['name']

    if (user['name'] in watched or user['id'] in watched) and is_online:
      print(user['name'], "is watched and went online!")
      if config['email']['enabled']:
        mailsendonlinewatched(user['name'], game_name, updated_at)
    elif is_online and config['watchedonly'] == False:
      print(user['name'], "went online!")
      if config['email']['enabled']:
        mailsendonline(user['name'], game_name, updated_at)
    elif not is_online:
      print(user['name'], "went offline.")

# Iterate through friends and call the check function
for friend in friends:
  check_and_send_email(friend)
                
config['lastcheck'] = datetime.datetime.now().isoformat()

with open(configpath, 'w') as outfile:
    yaml.dump(config, outfile, default_flow_style=False)
© www.soinside.com 2019 - 2024. All rights reserved.