ChatGPT解决这个技术问题 Extra ChatGPT

Send Outlook Email Via Python?

I am using Outlook 2003.

What is the best way to send email (through Outlook 2003) using Python?

@ThiefMaster: my smtp server is not the same as my email -- hence, I need to channel my smtp through my internet provider (att), even though I am using a different email address (not att's) to send the email. Outlook is already configured to handle this. If there are other solutions (non-Outlook based) that will also support this, I'd be happy to hear suggestions.
The proper solution is using python's smtplib

T
TheoretiCAL
import win32com.client as win32
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = 'To address'
mail.Subject = 'Message subject'
mail.Body = 'Message body'
mail.HTMLBody = '<h2>HTML Message body</h2>' #this field is optional

# To attach a file to the email (optional):
attachment  = "Path to the attachment"
mail.Attachments.Add(attachment)

mail.Send()

Will use your local outlook account to send.

Note if you are trying to do something not mentioned above, look at the COM docs properties/methods: https://msdn.microsoft.com/en-us/vba/outlook-vba/articles/mailitem-object-outlook. In the code above, mail is a MailItem Object.


Updated answer. mail.HTMLBody lets you set it to a string of html
Simple and straight answer! Working correctly in Python 3.6.1.
@ViktorDemin Looking at the official COM docs, msdn.microsoft.com/en-us/vba/outlook-vba/articles/…, I would try mail.ReadReceiptRequested = True
@pyd try simply a colon seperated string of emails in the mail.To = "a@b.com;c@d.com", let me know if it works
A
Adriaan

For a solution that uses outlook see TheoretiCAL's answer.

Otherwise, use the smtplib that comes with python. Note that this will require your email account allows smtp, which is not necessarily enabled by default.

SERVER = "smtp.example.com"
FROM = "yourEmail@example.com"
TO = ["listOfEmails"] # must be a list

SUBJECT = "Subject"
TEXT = "Your Text"

# Prepare actual message
message = """From: %s\r\nTo: %s\r\nSubject: %s\r\n\

%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)

# Send the mail
import smtplib
server = smtplib.SMTP(SERVER)
server.sendmail(FROM, TO, message)
server.quit()

EDIT: this example uses reserved domains like described in RFC2606

SERVER = "smtp.example.com"
FROM = "johnDoe@example.com"
TO = ["JaneDoe@example.com"] # must be a list

SUBJECT = "Hello!"
TEXT = "This is a test of emailing through smtp of example.com."

# Prepare actual message
message = """From: %s\r\nTo: %s\r\nSubject: %s\r\n\

%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)

# Send the mail
import smtplib
server = smtplib.SMTP(SERVER)
server.login("MrDoe", "PASSWORD")
server.sendmail(FROM, TO, message)
server.quit()

For it to actually work with gmail, Mr. Doe will need to go to the options tab in gmail and set it to allow smtp connections.

Note the addition of the login line to authenticate to the remote server. The original version does not include this, an oversight on my part.


This was not the question. The question is about using the Win32 API in order to control Outlook
@Spencer Rathbun: thank you. The problem is this: my smtp server is not the same as my email -- hence, I need to channel my smtp through my internet provider (att), even though I am using a different email address (not att's) to send the email. Outlook is already configured to handle this. If there are other solutions (non-Outlook based) that will also support this, I'd be happy to hear suggestions.
@user3262424 So your email address is not the same as your smtp server? That should be handled on the smtp server. It needs to be set to pass on emails that don't originate there to the proper email server. Incorrectly set up, this allows spammers to loop through you. But presumably, you know the ip addresses involved and can set them on an allow list.
@Spencer Rathbun: thank you, but I am not sure how to use your script. I am not successful sending an email using it.
If you are, God forbid, behind a corporate firewall, you can only send mail via Outlook.
S
Steve Townsend

Check via Google, there are lots of examples, see here for one.

Inlined for ease of viewing:

import win32com.client

def send_mail_via_com(text, subject, recipient, profilename="Outlook2003"):
    s = win32com.client.Dispatch("Mapi.Session")
    o = win32com.client.Dispatch("Outlook.Application")
    s.Logon(profilename)

    Msg = o.CreateItem(0)
    Msg.To = recipient

    Msg.CC = "moreaddresses here"
    Msg.BCC = "address"

    Msg.Subject = subject
    Msg.Body = text

    attachment1 = "Path to attachment no. 1"
    attachment2 = "Path to attachment no. 2"
    Msg.Attachments.Add(attachment1)
    Msg.Attachments.Add(attachment2)

    Msg.Send()

thank you, this is good. The problem is, Outlook keeps generating an alert message asking me if I'd like to continue or alternatively, terminate the accessing script. Is there a way to skip this alert message?
@user3262424 - What's the exact content of the popup?
I am not next to that computer right now. Something informing that a script is trying to access outlook and that it might be a virus etc. and if I want to continue.
That could be some antivirus addin doing email screening then. I doubt you can bypass that without manual action on the desktop to disable it. Annoying.
Is there a way to do this same thing on Mac OS without win32 modules?
E
Edison

I wanted to send email using SMTPLIB, its easier and it does not require local setup. After other answers were not directly helpful, This is what i did.

Open Outlook in a browser; Go to the top right corner, click the gear icon for Settings, Choose 'Options' from the appearing drop-down list. Go to 'Accounts', click 'Pop and Imap', You will see the option: "Let devices and apps use pop",

Choose Yes option and Save changes.

Here is the code there after; Edit where neccesary. Most Important thing is to enable POP and the server code herein;

import smtplib

body = 'Subject: Subject Here .\nDear ContactName, \n\n' + 'Email\'s BODY text' + '\nYour :: Signature/Innitials'
try:
    smtpObj = smtplib.SMTP('smtp-mail.outlook.com', 587)
except Exception as e:
    print(e)
    smtpObj = smtplib.SMTP_SSL('smtp-mail.outlook.com', 465)
#type(smtpObj) 
smtpObj.ehlo()
smtpObj.starttls()
smtpObj.login('me@outlook.com', "password") 
smtpObj.sendmail('sender@outlook.com', 'recipient@gmail.com', body) # Or recipient@outlook

smtpObj.quit()
pass

This method also works with smtp.office365.com for those wondering.
C
Corey Goldberg

using pywin32:

from win32com.client import Dispatch

session = Dispatch('MAPI.session')
session.Logon('','',0,1,0,0,'exchange.foo.com\nUserName');
msg = session.Outbox.Messages.Add('Hello', 'This is a test')
msg.Recipients.Add('Corey', 'SMTP:corey@foo.com')
msg.Send()
session.Logoff()

thank you. Will this not generate the annoying outlook error message?
it might trigger a validation on newer versions of windows. not sure how you would suppress that. I don't run windows anymore.
A
Adriaan

A simple solution for Office 365 is

from O365 import Message

html_template =     """ 
            <html>
            <head>
                <title></title>
            </head>
            <body>
                    {}
            </body>
            </html>
        """

final_html_data = html_template.format(df.to_html(index=False))

o365_auth = ('sender_username@company_email.com','Password')
m = Message(auth=o365_auth)
m.setRecipients('receiver_username@company_email.com')
m.setSubject('Weekly report')
m.setBodyHTML(final)
m.sendMessage()

Here df is a dataframe converted to an html Table, which is being injected into html_template


m
miksus

This is a pretty old question but there is one more solution. The current Outlook SMTP server is (as of 2022):

Host: smtp.office365.com

Port: 587 (for TLS)

Probably the easiest and cleanest solution is to use Red Mail that has these already set:

pip install redmail

Then:

from redmail import outlook

outlook.user_name = "example@hotmail.com"
outlook.password = "<MY PASSWORD>"

outlook.send(
    receivers=["you@example.com"],
    subject="An example",
    text="Hi, this is an example."
)

Red Mail supports all sorts of advanced features:

HTML and text bodies

Attachments from various types

Embedded images

It also has Jinja support

Links:

Documentation: https://red-mail.readthedocs.io/en/latest/

Source code: https://github.com/Miksus/red-mail

Disclaimer: I'm the author


L
LinconFive

Other than win32, if your company had set up you web outlook, you can also try PYTHON REST API, which is officially made by Microsoft. (https://msdn.microsoft.com/en-us/office/office365/api/mail-rest-operations)


c
clemens

This was one I tried using Win32:

import win32com.client as win32
import psutil
import os
import subprocess
import sys

# Drafting and sending email notification to senders. You can add other senders' email in the list
def send_notification():


    outlook = win32.Dispatch('outlook.application')
    olFormatHTML = 2
    olFormatPlain = 1
    olFormatRichText = 3
    olFormatUnspecified = 0
    olMailItem = 0x0

    newMail = outlook.CreateItem(olMailItem)
    newMail.Subject = sys.argv[1]
    #newMail.Subject = "check"
    newMail.BodyFormat = olFormatHTML    #or olFormatRichText or olFormatPlain
    #newMail.HTMLBody = "test"
    newMail.HTMLBody = sys.argv[2]
    newMail.To = "xyz@abc.com"
    attachment1 = sys.argv[3]
    attachment2 = sys.argv[4]
    newMail.Attachments.Add(attachment1)
    newMail.Attachments.Add(attachment2)

    newMail.display()
    # or just use this instead of .display() if you want to send immediately
    newMail.Send()





# Open Outlook.exe. Path may vary according to system config
# Please check the path to .exe file and update below
def open_outlook():
    try:
        subprocess.call(['C:\Program Files\Microsoft Office\Office15\Outlook.exe'])
        os.system("C:\Program Files\Microsoft Office\Office15\Outlook.exe");
    except:
        print("Outlook didn't open successfully")     
#

# Checking if outlook is already opened. If not, open Outlook.exe and send email
for item in psutil.pids():
    p = psutil.Process(item)
    if p.name() == "OUTLOOK.EXE":
        flag = 1
        break
    else:
        flag = 0

if (flag == 1):
    send_notification()
else:
    open_outlook()
    send_notification()