I am trying to setup a script to send email, and I want to add the Senders Name (depending on who runs the script) to the Email Body.
Emailing works, and I'm setup on Juypter, runing Python 3, emailing from Outlook.
My code is below. The mail.SenderName is the part I want to pull the name from the Outlook account of the user. In VBA this would be equivalent to using Application.UserName
import win32com.client as win32
outlook = win32.Dispatch("outlook.application")
mail = outlook.CreateItem(0)
mail.To = "user#somewhere.com"
mail.Subject = "Report"
#Text for email
mail.HTMLBody = "Dear All,<br><br>" \
"The latest version of the Report is attached in PDF format.<br><br>" \
"Kind Regards <br><br>" \
mail.SenderName
attachment = filename
mail.Attachments.Add(attachment)
mail.Send()
So I would want the email body to be:
Dear All,
The latest version of the Report is attached in PDF format.
Kind Regards
Bob Smith
Any help, much appreciated.
UPDATE
By combining the response from Error - Syntactical Remorse and Eugene Astafiev, with a bit more searching, I managed to resolve the issue. Thank you for the guidance.
Full code is:
outlook = win32.Dispatch("outlook.application")
mail = outlook.CreateItem(0)
mail.To = "user#somewhere.com"
mail.Subject = "Report"
sender = outlook.GetNamespace("MAPI").CurrentUser.Name
#Text for email
mail.HTMLBody = "Dear All,<br><br>" \
"The latest version of the Report is attached in PDF format.<br><br>" \
"Kind Regards <br><br>" \
f"{sender}"
attachment = filename
mail.Attachments.Add(attachment)
mail.Send()
You can:
Use the NameSpace.CurrentUser property which returns the display name of the currently logged-on user as a Recipient object.
Sub DisplayCurrentUser()
Dim myNamespace As Outlook.NameSpace
Set myNameSpace = Application.GetNameSpace("MAPI")
MsgBox myNameSpace.CurrentUser.Name
End Sub
If it is set, you may use the MailItem.SendUsingAccount property which returns an Account object that represents the account under which the MailItem is to be sent.
MailItem.SendUsingAccount.DisplayName
Related
I am writing a python script that sends every day a bulk email (connected to an outlook.com account) with the body of a news website as an ebook to multiple kindle accounts (that have already whitelisted this outlook account).
This was working so far, but since yesterday the kindle devices couldn't get the ebooks. I've tried a lot and I found out, that the problem is because all the sent emails have the receiver in the BCC part of the email. For some reason since yesterday if the receiver is on BCC, kindle doesn't receive the email (or process it).
So I am asking, what should I change on my code so I could have the receiver addresses on the [TO] part of the email instead of the [BCC]. I don't mind if it's a single email with multiple addresses or multiple single emails, as far as the receiver is not on the BCC.
receiver_email = ["email1#mail.com", "email2#mail.com", "email3#mail.com", "email4#mail.com", "email5#mail.com"]
subj = "Issue - "+fullDate
msg = MIMEMultipart('alternative')
msg['Subject'] = subj
msg['From'] = sender_email
msg.attach(MIMEText('Forward this email to your kindle account'))
# Attach the .mobi file
print("Attaching "+epubname)
fp = open(epubname, "rb")
epub_file = MIMEApplication(fp.read())
fp.close()
encoders.encode_base64(epub_file)
epub_file.add_header('Content-Disposition', 'attachment', filename=epubname)
msg.attach(epub_file)
debug = False
if debug:
print(msg.as_string())
else:
server = smtplib.SMTP('smtp.office365.com',587)
server.ehlo()
server.starttls()
server.login("##EMAIL##", "##PASSWORD##")
text = msg.as_string()+ "\r\n" + message_text
for x in range(len(receiver_email)):
email_to = receiver_email[x]
msg['To'] = email_to #msg['To'] = ", ".join(email_to)
server.sendmail(sender_email, email_to, text.encode('utf-8'))
server.quit()
I've found this question, but with no specific answer unfortunately.
Your code seems to be written for Python 3.5 or earlier. The email library was overhauled in 3.6 and is now quite a bit more versatile and logical. Probably throw away what you have and start over with the examples from the email documentation.
The simple and obvious solution is to put all the recipients in msg["to"] instead of msg["bcc"].
Here is a refactoring for Python 3.3+ (the new API was informally introduced already in 3.3).
from email.message import EmailMessage
receiver_email = ["email1#mail.com", "email2#mail.com", "email3#mail.com", "email4#mail.com", "email5#mail.com"]
subj = "Issue - "+fullDate
msg = EmailMessage()
msg['Subject'] = subj
msg['From'] = sender_email
msg['To'] = ", ".join(receiver_email)
msg.set_content('Forward this email to your Kindle account')
with open(epubname, "rb") as fp:
msg.add_attachment(fp.read()) # XXX TODO: add proper MIME type?
debug = False
if debug:
print(msg.as_string())
else:
with smtplib.SMTP('smtp.office365.com',587) as server:
server.ehlo()
server.starttls()
server.login("##EMAIL##", "##PASSWORD##")
server.send_message(msg)
This sends a single message to all the recipients; this means they can see each others' email addresses if they view the raw message. You can avoid that by going back to looping over the recipients and sending one message for each, but you really want to avoid that if you can.
As an aside, you don't need range if you don't care where you are in the list. The idiomatic way to loop over a list in Python is simply
for email_to in receiver_email:
...
I'm having an issue like this one
outlook = win32com.client.Dispatch('outlook.application')
accounts = win32com.client.Dispatch("outlook.Application").Session.Accounts
print(accounts[1])
mail = outlook.CreateItem(0)
mail.SentOnBehalfOfName = accounts[1]
mail.SendUsingAccount = accounts[1]
mail.To = to
mail.Subject = 'Subject TEST'
mail.HTMLBody = emailBody
mail.display()
mail.Send()
if I comment mail.Send() the window that shows up will show everything correctly but if I send it, i'll get reply This message could not be sent. You do not have the permission to send the message on behalf of the specified user. which is obviously not true since if instead of sending directly and choose the exact same email from the dropdown menu in From, and then click SEND, it will send the email with no issues.
So with the help of #Eugene Astafiev and this post I fixed the issue like this:
outlook = win32com.client.Dispatch('outlook.application')
for account in outlook.Session.Accounts:
if account.DisplayName == "marhaba#vodafone.om":
print(account)
mail = outlook.CreateItem(0)
mail._oleobj_.Invoke(*(64209, 0, 8, 0, account))
mail.To = to
mail.Subject = 'Vodafone Support'
mail.HTMLBody = emailBody
#mail.display()
mail.Send()
There is no need to use these both properties at the same time in Outlook:
mail.SentOnBehalfOfName = accounts[1]
mail.SendUsingAccount = accounts[1]
The From field available in the Outlook UI corresponds to the MailItem.SendUsingAccount property which returns or sets an Account object that represents the account under which the MailItem is to be sent. This option is available when you have multiple accounts configured in Outlook.
The MailItem.SentOnBehalfOfName property returns a string, not an Account instance, where a string indicates the display name for the intended sender of the mail message. Be aware, the permission should be given to be able to send on behalf of another person in Exchange.
So, if you have got multiple accounts configured in Outlook you may go with the following line of code:
mail.SendUsingAccount = accounts[1]
I already referred this post. Don't mark it as duplicate please.
I wrote the below code to send an email via python
outlook = win32com.client.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
From = outlook.Session.Accounts[1]
mail.To = 'test#org.com'
mail.Subject = 'Test Email'
mail.HTMLBody = '<h3>This is HTML Body</h3>'
mail.Body = "This is the normal body"
mail._oleobj_.Invoke(*(64209, 0, 8, 0, From))
mail.Send() # successfully executed
The above code is successfully executed but still the email is not delivered and its been more than 15 mins. If I do it manually using outlook,am able to send and receive messages.
Can help me what is the issue here?
update - mail.display() looks like below
update - mail.Send() in outbox looks like below
update - error for 2nd mailbox
update - code
mail = outlook.CreateItem(0)
for acc in outlook.Session.Accounts:
if acc.DisplayName == 'user2#org.com':
print("hi")
mail.SendUsingAccount = acc.DisplayName
mail.To = 'user1#org.com'
mail.Subject = 'Test Email'
mail.HTMLBody = '<h3>This is HTML Body</h3>'
mail.Body = "This is the normal body"
mail._oleobj_.Invoke(*(64209, 0, 8, 0, mail.SendUsingAccount))
pythoncom.CoInitialize()
The difference between Outlook and your code is the synchronization with the mail server. Outlook may cache submitted items and send them when the store is synced with the mail server.
The NameSpace.SendAndReceive method initiates immediate delivery of all undelivered messages submitted in the current session, and immediate receipt of mail for all accounts in the current profile. SendAndReceive provides the programmatic equivalent to the Send/Receive All command that is available when you click Tools and then Send/Receive. All accounts defined in the current profile are used in Send/Receive All. If an online connection is required to perform the Send/Receive All, the connection is made according to user preferences.
Read more about that in the How To: Perform Send/Receive in Outlook programmatically article.
Also you may try to run the following code:
mail = outlook.CreateItem(0)
for acc in outlook.Session.Accounts:
if acc.DisplayName == 'user2#org.com':
print("hi")
mail.SendUsingAccount = acc.DisplayName
mail.To = 'user1#org.com'
mail.Subject = 'Test Email'
mail.HTMLBody = '<h3>This is HTML Body</h3>'
mail.Body = "This is the normal body"
mail.Send()
I want to reply a mail in Outlook web application using Python. I'm using the package win32com.client for sending the mails but not getting anything regarding reply. Can anyone please share the code....
You find the Application Object API under
https://learn.microsoft.com/de-de/office/vba/api/outlook.application
'replying to an E-Mail' is not generic, since you must look it up in you custom folder structure.
For introduction an example of the API usage (sending an e-mail):
import win32com.client as win32
if __name__ == '__main__':
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = 'someone#example.com'
mail.Subject = 'Something important'
# to set a text-body
mail.Body = 'Lorem Ipsum'
# for completness only, the html-body:
mail.HTMLBody = '<h1>HTML Message body</h1>'
attachment = "Path to the attachment"
mail.Attachments.Add(attachment)
mail.Send()
pass
I have a script that automatically creates and sends emails sends emails using the simple function below:
def Emailer(text, subject, recipient):
import win32com.client as win32
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = recipient
mail.Subject = subject
mail.HtmlBody = text
mail.send
But how do I open this email in an Outlook window so that it can be manually edited and sent?
Ideally, I'd like something like this:
def __Emailer(text, subject, recipient, auto=True):
import win32com.client as win32
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = recipient
mail.Subject = subject
mail.HtmlBody = text
if auto:
mail.send
else:
mail.open # or whatever the correct code is
Call mail.Display(True) instead of mail.send.
tldr: Use mail.Display(False) instead of mail.Display(True)
mail.Display(False) will still display the window.
If you use mail.Display(True) the scripts stops until the window is closed. So use mail.Display(False) this will open the window and your python script will move on to the next command. It is also useful to know that you can use mail.save() to save as draft in the draft folder.
Visit https://msdn.microsoft.com/en-us/VBA/Outlook-VBA/articles/mailitem-display-method-outlook to read more on this
I like the solution :) But I want to add some infos:
Using the solution, it is probably the best way to add a mail input with Html format for modification.
Also add the file from the working directory...
#requirements.txt add for py 3 -> pypiwin32
def Emailer(text, subject, recipient):
import win32com.client as win32
import os
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = recipient
mail.Subject = subject
mail.HtmlBody = text
###
attachment1 = os.getcwd() +"\\file.ini"
mail.Attachments.Add(attachment1)
###
mail.Display(True)
MailSubject= "Auto test mail"
MailInput="""
#html code here
"""
MailAdress="person1#gmail.com;person2#corp1.com"
Emailer(MailInput, MailSubject, MailAdress ) #that open a new outlook mail even outlook closed.
Here is another option with saving the mail on disk first:
import webbrowser
mail.SaveAs(Path=save_path)
webbrowser.open(save_path)
This way the mail opens maximized.