How to send a variable through email - python

I am trying to send a 2 step verification code for an assignment and everything works but when i recieve the email there is no number. For Loop creates random 6 digit code. It says: Please confirm your login by entering this 2-step verification code. None'
I have looked on stack over flow for solutions and google etc
def TwoStep():
for x in range(1):
RandomNumber = print(random.randint(100000,1000000))
time.sleep(5)
email_send = 'recieving email'
email_user = 'myemail'
email_password = 'password'
subject = '2-Step Verification'
msg = MIMEMultipart()
msg['From'] = email_user
msg['To'] = email_send
msg['Subject'] = subject
body = ('Please confirm your login by entering this 2-step verification code. ' + str(RandomNumber))
msg.attach(MIMEText(body,'plain'))
text = msg.as_string()
server = smtplib.SMTP('smtp.gmail.com',587)
server.starttls()
server.login(email_user,email_password)
server.sendmail(email_user,email_send,text)
server.quit()
TwoStep()
Be able to send the 6 digit code through email.

A few things to comment:
1) print(random.randint(100000,1000000)) prints the number in the console but doesn't returns anything, that's why you are getting a None value.
2) DON'T use capital case variables, by convention these names are reserved for naming Classes and it's confusing to see this names as a variable. Note that even the SO highlighting marks it in another color. Use some camel-case or snake-case naming such as randomNumber or random_number (these one more common in Python).
3) Is the for loop even necessary? I think you only need to generate a random number, so you can remove the loop around it, and just assign it once.

your code is not returning a random number instead printing it and why is loop added ?
for x in range(1):
RandomNumber = print(random.randint(100000,1000000))

Related

Mass Email Via Python, Custom Body

New to Python, I'm trying to write a mass-email script (it will be sent via gmail).
Basically I have got it working, however I need to edit each message body separately with a greeting to name of the e-mail recipient. Currently the body is read off a body.txt file and I am not sure how to edit it. Example:
body.txt
Hi <recipient>,
Here is your voucher code.
And this is my script, send_email.py:
import smtplib
from email.mime.text import MIMEText
from_address = "xyz#gmail.com"
file = open("body.txt","rb")
message = MIMEText(file.read())
file.close()
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(from_address, "XXXXX")
server.set_debuglevel(1)
sender = from_address
recipients = ['abc#gmail.com', 'def#gmail.com']
message['Subject'] = "Voucher Code"
message['From'] = sender
message['To'] = ", ".join(recipients)
server.sendmail(sender, recipients, message.as_string())
I think most probably I will have to create another list with the names of recipients and match them to the email addresses to be sent to, but I'm not sure how to go from there. In fact, I'm not even sure this is the best way- it works though, so I'm pretty happy so far, apart from not being able to edit the body. How do I go from here?
I've seen what you did and I think it's a great start. To edit in the recipients name to the message is really quite simple. You need to format the string. Here's an example:
emailBody = "Hello {}, this is my email body. As you can see this program inserts every recipient separately. Hopefully it is helpful. \n"
recipients = ["Ann", "Josh", "Bob", "Marie"]
for recipient in recipients:
print(emailBody.format(recipient))
The main thing is that your emailBody must include symbols {} and then you can use
emailBody.format(content)
to put something into those brackets.

Sending gmail emails through python + smtplib. Can't separate body from subject

I want to send emails from my gmail acocunt through a python script.
And my code works.
The only thing is I want the emails to have a subject and a body.
But my script is putting everything in the subject.
Here's my code:
import smtplib
with smtplib.SMTP("smtp.gmail.com", 587) as smtp:
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
smtp.login("MY EMAIL", "MY PASSWORD")
subject = "Contract Details"
body = "Grettings. Here are the contract details. Thank you."
msg = f"""Subject: {subject}\n\n{body}"""
email = "MY EMAIL"
def encode(x):
""" The replaces in this function fix some problems in the encoding.
For now, they are not that relevant. They work. """
return str(x.encode("ascii", errors="ignore")).replace("b'", "").replace("'", "")
# I'm sending it to myself, so the first two arguments are the same:
smtp.sendmail(encode(email), encode(email), encode(msg))
I've tried to figure out the solution online, and a lot of videos and articles say that you should use two newlines to separate the subject from the body.
That's why I'm using msg = f"""Subject: {subject}\n\n{body}"""
However, I get this:
As you can see both my subject and body are in the subject (red), and the body is blank.
I've also tried no breaklines, one breakline, three breaklines.
I even tried to write msg = f"""Subject: {subject}\n\nBody: {body}"""
But nothing works...
How do I separate the body from the subject?
Ok, so I changed:
smtp.sendmail(encode(email), encode(email), encode(msg))
To:
smtp.sendmail(encode(email), encode(email), msg)
And now it works.

Can't find certain files.

I am trying to write a script that will look for a file and the script is running fine but is running as if it could never be found? However I know this file is there. It will run and also send multiple emails when I just want it to send one email instead of multiple. (I've removed my email and password for obvious reasons but the blank strings are my Email address/Password and I am aware of this.
This is my code:
for path, dirs, files in os.walk(bureau):
for filename in files:
filename_no_ext, ext = os.path.splitext(filename)
if ext.lower() == '.xls':
num = filename.rsplit(" ")
jnum = num[0]
if num[0] in jobnums:
master = ' '.join([jnum, "Master Box File List.xls"])
for jobfolder in os.listdir(bureau):
if jobfolder.startswith(jnum):
if os.path.exists(master):
print master
else:
fromaddr = ""
toaddr = ""
max_attempts = 5
login_success = False
for i in range(max_attempts):
try:
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "Scripting Email"
body = "This email is an automatic email part of a Python training excersise"
msg.attach(MIMEText(body, 'plain'))
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(fromaddr, "")
text = msg.as_string()
print "Signed In To Mailbox."
login_success = True
break
except:
print "Can't Sign In To Mailbox. Trying Again...."
time.sleep(0.5)
continue
if login_success:
server.sendmail(fromaddr, toaddr, text)
server.quit()
print "Email Sent."
else:
print "Can't Sign In To Mailbox."
Im not expecting this to be a huge error just something small that I can't see, cheers guys.
I'm going to take a wild guess that you don't actually mean to do
for jobfolder in os.listdir(bureau):
It looks like bureau is your top level directory. It never changes in the code. So for every file in your walk, you are running this for loop on the top level directory. What are you actually trying to loop over? If you're just checking for each file in the tree, you don't need another nested loop here, os.walk will already descend the full tree.

Python: Sending Email to Multiple Recipients

I'm trying to send email to multiple people using Python.
def getRecipients(fileWithRecipients):
recipients = []
f = open(fileWithRecipients, 'r')
for line in f:
recipients.append(line)
return recipients
def test_email():
gmail_user = "csarankings#gmail.com"
gmail_pass = getPassword("pass.txt")
FROM = "csarankings#gmail.com"
TO = getRecipients("recipients.txt")
date = getCurrentDate()
SUBJECT = "Current CSA Rankings: " + date
TEXT = createEmailMessageFromFile("rankings.txt")
message = """\From: %s\nTo: %s\nSubject: %s\n\n%s """ % (FROM, ", ".join(TO), SUBJECT, TEXT)
try:
server = smtplib.SMTP("smtp.gmail.com", 587)
server.ehlo()
server.starttls()
server.login(gmail_user, gmail_pass)
server.sendmail(FROM, TO, message)
server.close()
print("it worked")
except:
print("it failed :(")
For whatever reason, my emails only go to the first recipient in my list of recipients (the TO variable within my test_email() function.
My recipients file just consists of an email address per line (only has two in there at the moment). I thought there might be something wrong with my getRecipients() function, so I just hardcoded two emails into the TO variable and it works for the first email address and not the second.
Any idea why this might be happening? I suspect it has something to do with:
", ".join(TO)
where I set my message variable.
NB: My test_email() is largely based on the most upvoted answer here:
How to send an email with Gmail as provider using Python?
EDIT: For what it's worth, when I hardcode a list of a single email address into the TO variable, the subject displays properly in the email. When I use the getRecipients() function (even with only one email address in the recipients.txt file), it displays this in the body of the email:
Subject: Current CSA Rankings 6/13/15
Not sure if relevant but thought it might be related to the issue.
EDIT_2: I don't think my question is a duplicate of:
How to send email to multiple recipients using python smtplib?
because, while I use the smtplib.sendmail() function, I don't use the email module at all, so our code is very different...
I was able to do this by iterating over the list of recipients after logging on to the server.
Something like this
try:
server = smtplib.SMTP("smtp.gmail.com", 587)
server.ehlo()
server.starttls()
server.login(gmail_user, gmail_pass)
print('Login successful')
except:
print('Login unsuccessful')
And then iterating over list
for item in List:
TO = item
FROM = gmail_user
#message as defined above
try:
server.sendmail(FROM, TO, message)
except:
print('not sent for' + item)
server.close()

How do you check an email server (gmail) for a certain address and run something based on that address?

I've been trying to use 'import poplib' to access gmail, since I have Pop turned on in settings- but how do I actually then check the message for its 'from' address and then run something based on it? Also, what would be the command to strip the 'body' text from the message?
Here is how you can get subject and sender of each message in your GMail inbox using imaplib.
import imaplib
from email.parser import HeaderParser
conn = imaplib.IMAP4_SSL('imap.gmail.com')
conn.login('username#gmail.com', 'password')
# Select the mail box
status, messages = conn.select('INBOX')
if status != "OK":
print "Incorrect mail box"
exit()
if int(messages[0]) > 0:
for message_number in range(1,int(messages[0])+1):
data = conn.fetch(message_number, '(BODY[HEADER])')
parser = HeaderParser()
msg = parser.parsestr(data[1][0][1])
print "Subject: %s" % msg['subject']
print "From: %s" % msg['from']
You will probably need more information. Start from the official imaplib documentation.
there is the module rfc822
I guess messages from poplib can be donloaded from the server.
then put into a file
>>> f = StringIO.StringIO(message)
>>> import rfc822
and passed to
>>> rfc822.Message(f)
try this out.. and also check out the module documentation.
I hope it helps.
There is another python module:
>>> import email
>>> email.message_from_string(...)
This should provide you with read access for headers and also support muliple formats of body contents.
From the documentation:
POP3.retr(which)
Retrieve whole message number which, and set its seen flag. Result is in form (response, ['line', ...], octets).
So, assuming you have put the result of retr() into a variable called response, the lines of the message are stored as a list in response[1]. By RFC 2822 we know that the headers are separated from the body of the message by a blank line. The sender of the message will be in the From: header line. So we can just iterate over the lines of the message, stop when we get a blank line, and set a variable to our sender when we see a line that starts with From:.
sender = None
for line in response[1]:
if line.startswith("From: "):
sender = line.partition(" ")[2].strip()
elif line == "":
break
If you plan to do a lot with the headers, it might be useful to put them into a dictionary by header name. Since each header can appear multiple times, each value in the dictionary should be a list.
headers = {}
for line in response[1]:
if line == "":
break
line = line.partition(" ")
key = line[0].strip().rstrip(":")
value = line[2].stirp()
headers.setdefault(key, []).append(value)
After this you can use headers["From"][0] to get the sender of the message.
I wanted to show the basic way of doing this, because it's not very complicated, but Python can do most of the work for you. Again, assuming that your retr() result is in response:
import email
# convert our message back to a string and parse it
headers = email.parsefromstring("\n".join(response[0]), headersonly=True)
print headers["From"] # prints the sender
You can find out more about the message object in the documentation for the email module.
The From: line of an e-mail message may have additional text besides the e-mail address, such as the sender's name. You can extract the email address with a regular expression:
sender = re.find(r".*[ <](.+#.+)\b", headers["From"]).match(1)

Categories

Resources