Send email at specific time with millisecond precision - python

I would like to send email at given time preferably using gmail. The rationale behind this is that the school I am applying is ordering candidates based on when they receive the participation email after given time.
I could use gmail schedule send feature but there is X delay between sending email from gmail server to school email and it potentially should be achieveable to cut it down slightly so I thought about python script to do it. I think I can get around sending it at a given time but struggle to actually send the message.
There are threads in stackoverflow suggesting python solution e.g.: How do I schedule an email to send at a certain time using cron and smtp, in python? but unfortunately it looks like gmail disabled the option to send mails from non-authorized apps.
Other threads suggest that enabling less secure apps is needed. Unfortunately, this setting has been closed by Google. What could be the way around it?
My sample code:
`
def send_mail():
try:
server_ssl = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server_ssl.ehlo() # optional
print('Server initialized')
sent_from = gmail_user
to = ['xxxxxxxx#gmail.com']
subject = 'my subject'
body = 'my body'
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
server_ssl.sendmail(sent_from, to, email_text)
server_ssl.close()
except Exception as inst:
print('Something went wrong')
print(type(inst)) # the exception instance
print(inst.args) # arguments stored in .args
print(inst)
`
is returning an error:
<class 'smtplib.SMTPSenderRefused'> (530, b'5.7.0 Authentication Required. Learn more at\n5.7.0 https://support.google.com/mail/?p=WantAuthError

You need to supply the login to the account, as well as an apps password. You cant just send an email without being authenticated to the mail server.
with smtplib.SMTP_SSL('smtp.gmail.com', 465, context=context) as server:
print( 'waiting to login...')
server.login(sender_email, password)
print( 'waiting to send...')
server.sendmail(sender_email, receiver_email, text)

Related

How to use SMTP with Apple iCloud Custom Domain

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)

Can't send multiple emails because I get aborted (disconnected)

I'm getting a "aborted (disconnected)" when sending multiple emails with smtplib (python 3.6) and I can't find much information online. I'm pretty sure the error is coming from the server and not my code but I'd like to know how to fix this or at least get a clue of what to google to get more information because I am clueless as to how I am going to fix this.
This is the function I'm using the send one e-mail: ( I am calling this function five times and I'm getting the error ).
import smtplib
def enviar_um_mail(to, subject, body):
#source: https://stackabuse.com/how-to-send-emails-with-gmail-using-python/
user = '<mail here>'
password = '<passwrd here>'
sent_from = user
to = 'somemail#somedomain.org'
email_text = 'text of e-mail here'
try:
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.ehlo()
server.login(user, password)
server.sendmail(sent_from, to, email_text)
server.close()
print ('Email sent!')
except Exception as e:
print ('Something went wrong...')
print(e)
When calling this function five times the python shell shows:
Email sent!
Email sent!
Email sent!
Email sent!
Email sent!aborted (disconnected)

Python Email script trouble

I have a script that will be running nightly. I want it to send me an email when it fails to complete. I wrote a short test script to learn how to send an email with Python. In my IDE it runs without error messages but no email. I'm running from one of our servers (not the email server) which doesn't have any email restrictions.
I tried it in the Python shell so I can read any messages:
I tried sending to my gmail account and it get this error:
SMTPRecipientsRefused: {'blahblahblah#gmail.com': (550, '5.7.1 Unable to relay')}
Any ideas??
More info:
I modified the code found here to work with our email.
def send_email(user, recipient, subject, body):
import smtplib
FROM = user
TO = recipient if type(recipient) is list else [recipient]
SUBJECT = subject
TEXT = body
# Prepare actual message
message = """\From: %s\nTo: %s\nSubject: %s\n\n%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
try:
server = smtplib.SMTP("workemailserver.com")
server.sendmail(FROM, TO, message)
server.close()
print 'successfully sent the mail'
except:
print "failed to send mail"
With this I can send an email to my coworkers, but not myself. No biggie because I can use a coworkers email as the sender. Our "email server" relays the messages to office365, so that's why I cant send to my gmail.
My problem is basically solved. But I was never able to get the "simpler" code on top to work when I had tried sending to coworkers?
SMTPRecipientsRefused: (550, '5.7.1 Unable to relay')
This means the server you used can not relay the message to the target recipient. This usually happens when your email server has configuration issues.

No email sending using smtplib - python

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.

Sending email with python smtplib not working, confused about the "from" field

I'm trying to send an email in python. Here is my code.
import smtplib
if __name__ == '__main__':
SERVER = "localhost"
FROM = "sender#example.com"
TO = ["wmh1993#gmail.com"] # must be a list
SUBJECT = "Hello!"
TEXT = "This message was sent with Python's smtplib."
# Prepare actual message
message = """\
From: %s
To: %s
Subject: %s
%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
# Send the mail
server = smtplib.SMTP(SERVER)
server.sendmail(FROM, TO[0], message)
server.quit()
print "Message sent!"
This runs without error, but no email is sent to wmh1993#gmail.com.
Questions
One thing I don't understand about this code --- what restrictions do I have when setting the FROM field?
Do I somehow have to say that it was from my computer?
What is in place to prevent me from spoofing someone else's email?
Or am I at liberty to do that?
This runs without error, but no email is sent to wmh1993#gmail.com.
This usually means, the message was transferred to your MTA (mailserver) on 'localhost', but this server could not relay it to gmail. it probably tried to send a bounce message to "sender#example.com" and that failed as well. or it sent the message successfully but it landed in gmails spam folder (the message could trigger spam rules since it is missing a date header)
One thing I don't understand about this code --- what restrictions do I have when setting the FROM field?
it must be a syntactically valid email address
Do I somehow have to say that it was from my computer?
no. but that could be the problem why it was not delivered. is your computer on a home/dynamic/dial-up IP? gmail (and many many many other providers) don't accept mail from such IPs. the HELO of your mailserver might be wrong, DNS settings might be incorrect etc. you need to check the server logs. you probably have to configure your local mailserver to relay the message via a smarthost instead of trying to contact the target server directly.
What is in place to prevent me from spoofing someone else's email?
not much, that's why we have so much spam from forged adresses. things like SPF/DKIM can help a bit, but the SMTP protocol itself doesn't offer protection against spoofing.
Or am I at liberty to do that?
technically yes.
Well, since you don't specify exactly what kind of email server you are using and its settings, there are several things that might be wrong here.
First of all, you need to specify the HOST and the PORT of your server and connect to it.
Example:
HOST = "smtp.gmail.com"
PORT = "587"
SERVER = smtplib.SMTP()
SERVER.connect(HOST, PORT)
Then you need to specify an user and his password to this host.
Example:
USER = "myuser#gmail.com"
PASSWD = "123456"
Some servers require the TLS protocol.
Example:
SERVER.starttls()
Then you need to login.
Example:
SERVER.login(USER,PASSWD)
Only then you are able to send the email with your sendmail.
This example works pretty well in most common servers.
If you are using, as it seems, your own server, there aren't much changes you need to apply. But you need to know what kind of requirements this server has.
The "from" field in the email headers specifies the sender's email address. When using smtplib in Python to send an email, the "from" field can be set using the "from_address" argument in the smtplib.SMTP function. Here's an example:
import smtplib
sender_email = "sender#example.com"
recipient_email = "recipient#example.com"
message = "Subject: Example Email\n\nThis is an example email."
with smtplib.SMTP("smtp.example.com", 587) as smtp:
smtp.ehlo()
smtp.starttls()
smtp.login("sender#example.com", "password")
smtp.sendmail(sender_email, recipient_email, message)
Note that many email servers may reject emails that have a "from" address that doesn't match the login credentials.

Categories