I am trying to create a function to open a new Outlook message, but I would like the message to appear already with the recipient, subject fields.
So far what I have found is how to open a new Outlook window with the recipient, but I still can't get the subject to be displayed.
import webbrowser
webbrowser.open('mailto:email#domain.com', new=1)
Hope u can help me, ty.
mailto would work fine as long as you don't want HTML body or attachments. You can specify to/cc/bbc, subject, and body.
Something along the lines:
mailto:user1#domain.demo?subject=Test%20Subject&body=Test%20body&cc=user2#domain.demo&bcc=user3#domain.demo
And it will work under any OS and any email client.
Here is a potential solution using win32.com.client:
import win32.com.client as win32
outlook = win32.Dispatch("Outlook.Application") # Starts Outlook application
new_email = outlook.CreateItem(0) # Creates new email item
new_email.To = "email#domain.com" # Add recipients separated by comma or semicolon
new_email.Subject = "How to create new Outlook email in Python" # Your email subject
new_email.Body = "This text will be the body of your new email" # Your email body
new_email.Display(True) # Displays the new email item
Related
I am new to writing Python code and am trying to run a test to determine if an email attachment (.xls file) is encrypted with a password. I am using win32com to retrieve from Outlook and then loop through emails and attachments.
I've reviewed Microsoft documentation, but couldn't find what I need.
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox=outlook.GetDefaultFolder(6)
email_count = inbox.Items.count
messages = inbox.Items
for message in messages:
emailSendDate = message.senton.date()
attachments = message.attachments
emailSubject = message.Subject
for attachment in attachments:
attachment_name = attachment.filename
#a way to test if email attachment is encrypted?
Outlook knows nothing about a particular attachment type - it does not know and does not care. You would need to use the Excel Object Model to try to figure that out after you save the attachment using Attachment.SaveAsFile. Start at https://learn.microsoft.com/en-us/office/vba/api/excel.workbook.passwordencryptionfileproperties
I went the route of saving the attachment, but it would be much better if I could retrieve the temporary file path of the attachment and not need to save it. I tried using the GetTemporaryFilePath() method, but the rules of the method made it not work for me. For now, I used xlrd to test if it can open the workbook.
attachment.SaveAsFile(os.path.join(testfilepath, attachment.filename))
try:
wb = xlrd.open_workbook(os.path.join(testfilepath, attachment.filename))
attachmentEncryption = 'N'
except:
attachmentEncryption = 'Y'
I have prepared a draft email in Gmail that I need to send to several people but Gmail does not allow me to. The draft email has text, an image in it, and formatting.
I'd ideally want to send the draft to my list of contacts one by one just changing who it's addressed to. I can put the list of contacts in one column of excel and the name in another.
I could also just make the draft start with "Dear sir/madam" and send the same draft to my contacts without any modification.
If the body of my email was just text I guess I'd just use SMTP, but with all the formatting, and image in it I don't know what to do.
What is the easiest way to do this? Would using Selenium make sense? Anything else that's better?
Thanks
You could use a JavaMail API to send email.
For formatting you can use the html formatting inside your code, which serves like your draft.
Read the contacts from a file and replace the variable in "Dear" $varName.
And to trigger it multiple times you could use java.util.Timer class.
Hope it helps.
Here's what worked for me to send an email using python. I turned my email content into html and saved in a file and named it emailcontent. Then I used it in the following code:
import smtplib
from email.message import EmailMessage
from emailcontent import emailcontent
from config import email, password
email_list = ["user#gmail.com", "user2#yahoo.ca",
"user3#gmx.us", "user4#u.ca"]
for useremail in email_list:
msg = EmailMessage()
msg['Subject'] = 'Test'
msg['From'] = email
msg['To'] = useremail
msg.set_content('fallback')
msg.add_alternative(emailcontent, subtype='html')
with smtplib.SMTP_SSL("smtp.gmail.com", 465) as smtp:
smtp.login(email, password)
smtp.send_message(msg)
Looking to create and send messages with multiple files attached. Per the online gmail api documentation, there is a function for building messages with an attachment but no documentation for howto use it to create a message with multiple attachments.
Can I use the gmail API to send messages with multiple attachments programmatically? How might one do this?
With this function, you can send to one or multiple recipient emails, and also you can attach zero, one or more files. Coding improvement recommendations are welcome, however the way it is now, it works.
Python v3.7
smtplib from https://github.com/python/cpython/blob/3.7/Lib/smtplib.py (download the code and create the smtplib.py on your project folder)
def send_email(se_from, se_pwd, se_to, se_subject, se_plain_text='', se_html_text='', se_attachments=[]):
""" Send an email with the specifications in parameters
The following youtube channel helped me a lot to build this function:
https://www.youtube.com/watch?v=JRCJ6RtE3xU
How to Send Emails Using Python - Plain Text, Adding Attachments, HTML Emails, and More
Corey Schafer youtube channel
Input:
se_from : email address that will send the email
se_pwd : password for authentication (uses SMTP.SSL for authentication)
se_to : destination email. For various emails, use ['email1#example.com', 'email2#example.com']
se_subject : email subject line
se_plain_text : body text in plain format, in case html is not supported
se_html_text : body text in html format
se_attachments : list of attachments. For various attachments, use ['path1\file1.ext1', 'path2\file2.ext2', 'path3\file3.ext3']. Follow your OS guidelines for directory paths. Empty list ([]) if no attachments
Returns
-------
se_error_code : returns True if email was successful (still need to incorporate exception handling routines)
"""
import smtplib
from email.message import EmailMessage
# Join email parts following smtp structure
msg = EmailMessage()
msg['From'] = se_from
msg['To'] = se_to
msg['Subject'] = se_subject
msg.set_content(se_plain_text)
# Adds the html text only if there is one
if se_html_text != '':
msg.add_alternative("""{}""".format(se_html_text), subtype='html')
# Checks if there are files to be sent in the email
if len(se_attachments) > 0:
# Goes through every file in files list
for file in se_attachments:
with open(file, 'rb') as f:
file_data = f.read()
file_name = f.name
# Attaches the file to the message. Leaves google to detect the application to open it
msg.add_attachment(file_data, maintype='application', subtype='octet-stream', filename=file_name)
# Sends the email that has been built
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
smtp.login(se_from, se_pwd)
smtp.send_message(msg)
return True
Don't forget to activate less secure apps on your google account (https://myaccount.google.com/lesssecureapps) for this code to work.
Hope this helps
I have a working script that creates and sends Outlook emails successfully through pywin32, but I would like to send the email from a different, generic account. I have access to this generic account (and password) and even have the mailbox opened concurrently in Outlook, if that helps.
Trying something like msg.From = "generic#email.com" returns AttributeError: Property 'CreateItem.From' can not be set..
Is there any way to accomplish this without using SMTP? Even just changing the headers to reflect the generic account as the From and Reply-To address would work.
Edit: Using Win7 32bit, Outlook 2010, python 2.7, and the pywin32 module to create the following bit of code:
from win32com.client import Dispatch
mailer = Dispatch("Outlook.Application")
msg = mailer.CreateItem(0)
msg.To = emailTo
msg.CC = emailCC
msg.Subject = emailSubject
msg.Body = emailBody
msg.Send()
This part works perfectly fine, but it sends the emails through the user that's logged in, myself. I'd rather send it from a generic account so that it looks more official and replies are received there instead of in my mailbox.
I know this comes late, but this is another way I've managed to make this work. With this I was able to send e-mails with my non-default e-mail address in outlook:
import win32com.client as win32
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.Subject = "Test subject"
mail.To = "yourrecipient#gmail.com"
# If you want to set which address the e-mail is sent from.
# The e-mail needs to be part of your outlook account.
From = None
for myEmailAddress in outlook.Session.Accounts:
if "#gmail.com" in str(myEmailAddress):
From = myEmailAddress
break
if From != None:
# This line basically calls the "mail.SendUsingAccount = xyz#email.com" outlook VBA command
mail._oleobj_.Invoke(*(64209, 0, 8, 0, From))
mail.Send()
You can send mails via exchange using the extended mapi. It takes a little more effort than what you tried so far but it is very powerful, e.g. it allows to select an outlook profile to be used.
Have a look at site-packages\win32comext\mapi\demos\mapisend.py of your pywin32 installation.
EDIT:
As said in the comment, try the following to be sure Outlook is using the profile you want. Look for this line:
session = mapi.MAPILogonEx(0, MAPIProfile, None, mapi.MAPI_EXTENDED |
mapi.MAPI_USE_DEFAULT)
and change it to
session = mapi.MAPILogonEx(0, MAPIProfile, None, mapi.MAPI_EXTENDED |
mapi.MAPI_LOGON_UI)
Call SendEMAPIMail like this:
SendEMAPIMail(SendSubject, SendMessage, SendTo, MAPIProfile=None)
A dialog should appear offering to select the Outlook profile.
EDIT:
As #caseodilla found out, if Outlook is running with another profile, MAPILogonEx seems to reuse the running session and its profile. In order to force mapi to use another profile add the MAPI_NEW_SESSION flag:
session = mapi.MAPILogonEx(0, MAPIProfile, None, mapi.MAPI_EXTENDED |
mapi.MAPI_LOGON_UI | mapi.MAPI_NEW_SESSION)
I have this python IMAP script, but my problem is that, every time I want to get the sender's email address, (From), I always get the sender's first name followed by their email address:
Example:
Souleiman Benhida <souleb#gmail.com>
How can i just extract the email address (souleb#gmail.com)
I did this before, in PHP:
$headerinfo = imap_headerinfo($connection, $count)
or die("Couldn't get header for message " . $count . " : " . imap_last_error());
$from = $headerinfo->fromaddress;
But, in python I can only get the full name w/address, how can I get the address alone? I currently use this:
typ, data = M.fetch(num, '(RFC822)')
mail = email.message_from_string(data[0][1])
headers = HeaderParser().parsestr(data[0][1])
message = parse_message(mail) #body
org = headers['From']
Thanks!
Just one more step, using email.utils:
email.utils.parseaddr(address)
Parse address – which should be the value of some address-containing field such as To or Cc – into its constituent realname and email address parts. Returns a tuple of that information, unless the parse fails, in which case a 2-tuple of ('', '') is returned.
Note: originally referenced rfc822, which is now deprecated.
to = email.utils.parseaddr(msg['cc'])
This works for me.
My external lib https://github.com/ikvk/imap_tools
let you work with mail instead read IMAP specifications.
from imap_tools import MailBox, A
# get all emails from INBOX folder
with MailBox('imap.mail.com').login('test#mail.com', 'pwd', 'INBOX') as mailbox:
for msg in mailbox.fetch(A(all=True)):
print(msg.date, msg.from_, msg.to, len(msg.text or msg.html))
msg.from_, msg.to - parsed addresses, like: 'Sender#ya.ru'
I didn't like the existing solutions so I decided to make a sister library for my email sender called Red Box.
Here is how to search and process emails including getting the from address:
from redbox import EmailBox
# Create email box instance
box = EmailBox(
host="imap.example.com",
port=993,
username="me#example.com",
password="<PASSWORD>"
)
# Select an email folder
inbox = box["INBOX"]
# Search and process messages
for msg in inbox.search(unseen=True):
# Process the message
print(msg.from_)
print(msg.to)
print(msg.subject)
print(msg.text_body)
print(msg.html_body)
# Flag the email as read/seen
msg.read()
I also wrote extensive documentation for it. It also has query language that fully supports nested logical operations.