I would like to use Python's SMTP to send automated emails with a custom domain iCloud+ email address. However, I can't get logged into the SMTP servers. I will always either get "Mailbox does not exist" or "Authentication failed".
From the Apple support pages it seems like you need to use SSL over port 587. Additionally, they want you to generate an "app-specific password" for outside applications. This led me to the following code:
import smtplib, ssl
smtp_server = "smtp.mail.me.com"
port = 587 # For SSL
# Create a secure SSL context
context = ssl.create_default_context()
sender_email = "me#example.com" # Enter your address
receiver_email = "you#example.com" # Enter receiver address
password = "some,password" # app specific password from Apple ID settings
message = """\
To: {to}
From: {sender}
Subject: Hello There
This was sent through Python!
""".format(to=receiver_email, sender=sender_email)
with smtplib.SMTP_SSL(smtp_server, port, context=context) as server:
server.login(sender_email, password)
# Send email here
server.sendmail(sender_email, receiver_email, message)
However, this was still giving me a connection error. Only when I changed the last part to use TLS instead would it connect and give me an authentication error. This was taken from this question: SMTP_SSL SSLError: [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:590)
try:
server = smtplib.SMTP(smtp_server, port)
server.ehlo() # Can be omitted
server.starttls(context=context) # Secure the connection
server.ehlo() # Can be omitted
server.login(sender_email, password)
# Send email here
server.sendmail(sender_email, receiver_email, message)
except Exception as e:
import traceback
print(traceback.format_exc())
finally:
server.quit()
So how can I use my custom domain address with Apple's iCloud+ service with Python's SMTP?
Just before I was going to ask this question, I solved it!
After reading this reddit post, I figured that all custom domain iCloud+ accounts are actually alias of some sort to the main iCloud account. So, I tried logging into my "main" iCloud account. This worked with the above code and sent the email! However, the from was still not my custom domain email address.
This is a somewhat easy fix though, simply modify the "From: <sender>" line in the email body. I'm not sure if this should be done (since it's technicaly faking who you are) but it seems to work. If any email experts know of better ways to do this please comment/answer though! The following code is what I used:
sender_email = "me#icloud.com" # this is who we actually are
sender = "me#example.com" # this is who we appear to be (i.e. custom domain email)
receiver_email = "you#example.com" # this is to who we have sent the email
message = """\
To: {to}
From: {sender}
Subject: Hello There
This was sent through Python!
""".format(to=receiver_email, sender=sender) # this is what changed, we use an alias instead
# ...
server.sendmail(sender_email, receiver_email, message)
Related
I am trying to send an email using a python script like so:
import smtplib, ssl
port = 465
smtp_server = "smtp.gmail.com"
sender_email = "my#gmail.com"
receiver_email = "receiver#gmail.com"
password = "123456"
message = """\
Subject: Hi there
This message is sent from Python."""
context = ssl.create_default_context()
with smtplib.SMTP_SSL(smtp_server, port, context=context) as server:
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, message)
but unfortunately, Gmail blocks this connection, after running this code I receive an email saying that someone tried to access my account from an app that is not owned by Google, does anyone know a solution to this problem?
I'm trying to send a basic email with an attached document. The example I have works fine with a google address smtp.google.com, but when I try changing it over to smtp.office365.com, I get this error: [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:852).
This is a domain email that runs through the office365 SMTP server as a host for the email service. I've checked with the IT team, and they have turned on SMTP authentication on the account.
Obviously, this has been done before, so I have checked my code against this example, but don't see any obvious differences that could be causing it. I've also doubled checked the smtplib documentation, and smtp.office365.com is a valid, recognized SMTP address.
I've written this out as follows (note the confidential credentials which prevent a minimal reproducible example). I've noted where the error occurs, it's almost like smtplib is not recognizing the office365 SMTP address.
def send_email(self, html_message):
# Create a text/plain message
formatted_date = datetime.datetime.now().strftime('%Y%m%d')
msg_root = MIMEMultipart('related')
msg_root['Subject'] = self.client.client_name + 'Test Forecast'
msg_root['From'] = self.config.get_email_from
recipients = self.client.recipient_email
recipients = recipients.split(', ')
body = MIMEText(html_message, 'html')
msg_root.attach(body)
filename = self.client.city + ', ' + self.client.state
# PDF attachment
if self.client.use_pdf:
filepath = self.config.get_email_pdf_file_path
fp = open(filepath, 'rb')
att = email.mime.application.MIMEApplication(fp.read(), _subtype="pdf")
fp.close()
att.add_header('Content-Disposition', 'attachment', filename=filename + '.pdf')
msg_root.attach(att)
# SSL port config
port = 587
# Create a secure SSL context
context = ssl.create_default_context()
# Connect
with smtplib.SMTP_SSL("smtp.office365.com", port, context=context) as server: # Error on this line
server.ehlo()
server.starttls()
server.login(self.config.get_email_from, self.config.get_email_password)
print("Sending email report...")
# Send email
server.sendmail(self.config.get_email_from, recipients, msg_root.as_string())
print("Your email was sent!")
According to
error: [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:852)
You should use 465 port because you are using SSL protocol and 587 port is for TLS protocol.
It appears that because Microsoft uses port 587 for SMTP and the external domain we're using doesn't communicate via SSL, I had to change the port over to 587, remove the SSL argument from the method, and remove the context. With it now using SMTP rather than SSL, starttls was also necessary.
The working version looks like this:
port = 587
# Connect
with smtplib.SMTP("smtp.office365.com", port) as server:
server.ehlo()
server.starttls()
server.ehlo()
server.login(self.config.get_email_from, self.config.get_email_password)
print("Sending email report...")
# Send email
server.sendmail(self.config.get_email_from, recipients, msg_root.as_string())
print("Your email was sent!")
This question already has an answer here:
Getting unauthorized sender address when using SMTPLib Python
(1 answer)
Closed 2 years ago.
I tried sending an email with python using the email-provider "web.de".
I activated email protocols in the settings of the email service provider.
The following error message occurs:
(554, b'Transaction failed\nUnauthorized sender address.')
It should be possible to do it because my email programs can send emails.
import smtplib, ssl
smtp_server = "smtp.web.de"
port = 587 # For starttls
sender_email = "someemail#web.de"
password = input("Type your password and press enter: ")
receiver_email = "another#web.de"
message = "Subject: Hi there\n\nThis message is sent from Python."
# Create a secure SSL context
context = ssl.create_default_context()
# Try to log in to server and send email
try:
server = smtplib.SMTP(smtp_server,port)
server.ehlo() # Can be omitted
server.starttls(context=context) # Secure the connection
server.ehlo() # Can be omitted
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, message)
except Exception as e:
# Print any error messages to stdout
print(e)
finally:
server.quit()
First of all, I would advise you to use sendinblue, it is awesome and it is free to some extent.
Coming to your question, I don't think you should be asking for the senders password, since they might not give it to you. Next I think the senders email should have the email that you have registered with your email provider, not the email a person provides. The receiver email is good to go I guess. But I think this part has some problems:
try:
server = smtplib.SMTP(smtp_server,port)
server.ehlo() # Can be omitted
server.starttls(context=context) # Secure the connection
server.ehlo() # Can be omitted
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, message)
I think you forgot to write the subject of the email, which is likely triggering the error. I have never sent emails with python, but I have used python web framework django, and it shows error if the subject of the email is not provided.
Try this:
try:
server = smtplib.SMTP(smtp_server,port)
server.ehlo() # Can be omitted
server.starttls(context=context) # Secure the connection
server.ehlo() # Can be omitted
server.login(sender_email, password)
server.sendmail("This is the subject", sender_email, receiver_email, message)
also i think the receiver email should be a list, not just a string, because the number of recipients can change. Put it in a list like this even if you don't want to send it to a lot of people.
receiver_email = ["another#web.de"]
You can new recipients by putting a comma and writing the second recipient in quotes.
I've seen a lot of other posts with the same issue, I tried all of the following:
allow access to less secure app on gmail
Unlock token on google
make an app specific password
allow IMAP on gmail
Nothing is working, i still get the same error message:
SMTPAuthenticationError: (534, b'5.7.9 Please log in with your web browser and then try again. Learn more at\n5.7.9 https://support.google.com/mail/?p=WebLoginRequired s3sm5978501edm.78 - gsmtp')
This is my code on my python jupiter notebook:
sender_email = "xxx#gmail.com"
receiver_email = "yyy#gmail.com"
password = "xxxxxx"
message = MIMEMultipart("alternative")
message["Subject"] = "new properties for rent"
message["From"] = sender_email
message["To"] = receiver_email
# Create the plain-text and HTML version of your message
text = "Hi, new properties satisfy your search on daft: %s" % dictionary
html = "<html><body>%s</body></html>" % emailBody
# Turn these into plain/html MIMEText objects
part1 = MIMEText(text, "plain")
part2 = MIMEText(html, "html")
# Add HTML/plain-text parts to MIMEMultipart message
# The email client will try to render the last part first
message.attach(part1)
message.attach(part2)
# Create secure connection with server and send email
context = ssl.create_default_context()
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
server.ehlo()
server.login(sender_email, password)
server.sendmail(
sender_email, receiver_email, message.as_string()
)
There's a couple of reasons for this.
But since you exhausted most of them, and after talking in the comments. It's clear that you were sitting behind some sort of VPN or shared internet connection.
Some times, logging in on your account in a browser from this VPN/Shared connection would solve the problem. If not, the fastest and easiest way around this is to swap to a single-user connection (home wifi, dedicated VPS, something where only a handful of users might be sitting).
Common issues are: You're using Tor, a popular VPN provider, a school/company network.
Here's more information on the topic:
https://support.google.com/websearch/answer/86640?hl=en
import smtplib
sender = 'den.callanan#gmail.com'
receiver = ['callanden#gmail.com']
message = """From: From Person <den.callanan#gmail.com>
To: To Person <callanden#gmail.com>
Subject: SMTP e-mail test
This is a test e-mail message.
"""
try:
print("trying host and port...")
smtpObj = smtplib.SMTP('smtp.gmail.com', 465)
print("sending mail...")
smtpObj.sendmail(sender, receiver, message)
print("Succesfully sent email")
except SMTPException:
print("Error: unable to send email")
I've created two new email accounts (above), both on the same server (gmail) to test this.
It reaches the point in which it prints "trying host and port..." and does not go any further. So the problem should be with the address and port number I entered. But according to gmail's outgoing mail server details i've inputted them correctly. Any ideas what's wrong?
If I remove the port number or try a different port number such as 587 i'm provided with an error.
Sending email via Gmail's SMTP servers requires TLS and authentication. To authenticate, you will need to make an application-specific password for your account.
This script worked for me (though I used my own GMail email address and my own application-specific password). In the code below, replace APPLICATION_SPECIFIC_PASSWORD with the password you generated.
import smtplib
sender = 'den.callanan#gmail.com'
receiver = ['callanden#gmail.com']
message = """From: From Person <den.callanan#gmail.com>
To: To Person <callanden#gmail.com>
Subject: SMTP e-mail test
This is a test e-mail message.
"""
try:
print("trying host and port...")
smtpObj = smtplib.SMTP_SSL('smtp.gmail.com', 465)
smtpObj.login("den.callanan#gmail.com", "APPLICATION_SPECIFIC_PASSWORD")
print("sending mail...")
smtpObj.sendmail(sender, receiver, message)
print("Succesfully sent email")
except smtplib.SMTPException:
print("Error: unable to send email")
import traceback
traceback.print_exc()
(To debug the problem, I added the print-traceback code in the except statement. The exceptions had specific information on how to get it to work. The code hung when accessing port 465, I think because of problems with TLS negotiation, so I had to try using port 587; then I got good debugging info that explained what to do.)
You can see info on the SMTP_SSL object here.