通过Python发送Outlook邮件?

105

我正在使用 Outlook 2003

使用 Python,通过Outlook 2003 发送电子邮件的最佳方法是什么?


2
@ThiefMaster:我的smtp服务器与我的电子邮件不同,因此我需要通过我的网络提供商(ATT)“通道”我的smtp,即使我使用不同的电子邮件地址(非ATT的)发送电子邮件。 Outlook已经配置处理此问题。如果有其他解决方案(非基于Outlook的)也支持这一点,我很乐意听取建议。 - user3262424
正确的解决方案是使用Python的smtplib - ThiefMaster
9个回答

231
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()

将使用您本地的Outlook帐户发送。

如果您尝试执行以上未提及的操作,请查看COM文档属性/方法:https://msdn.microsoft.com/en-us/vba/outlook-vba/articles/mailitem-object-outlook。在上面的代码中,mail是一个MailItem对象。


3
更新的答案:mail.HTMLBody 允许您将其设置为一个 HTML 字符串。 - TheoretiCAL
7
简明直接的回答!可以在Python 3.6.1中正确运行。 - abautista
1
@ViktorDemin,看了一下官方的COM文档 https://msdn.microsoft.com/zh-cn/vba/outlook-vba/articles/mailitem-readreceiptrequested-property-outlook ,我建议尝试将mail.ReadReceiptRequested设置为True。 - TheoretiCAL
3
@pyd,尝试使用冒号分隔的电子邮件字符串在 mail.To = "a@b.com;c@d.com" 中,如果可以请告诉我。 - TheoretiCAL
1
@Ukrainian-serge 请看 https://pbpython.com/windows-com.html 和 https://learn.microsoft.com/de-de/windows/win32/com/component-object-model--com--portal?redirectedfrom=MSDN。 - Oliver Hoffmann
显示剩余11条评论

47

如果要使用Outlook的解决方案,请参见TheoretiCAL的答案

否则,使用Python自带的smtplib。请注意,这将需要您的电子邮件帐户允许SMTP,这不一定是默认启用的。

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()

编辑:此示例使用像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()

为了使其在Gmail上实际工作,Doe先生需要转到Gmail的选项标签,并将其设置为允许SMTP连接。

请注意添加登录行以对远程服务器进行身份验证。原始版本未包括此内容,这是我的疏忽。


16
好的,我会尽力进行翻译:这不是问题所在。问题是关于使用Win32 API来控制Outlook。 - user2665694
1
@user3262424,所以你的电子邮件地址与你的SMTP服务器不同?这应该在SMTP服务器上处理。它需要设置为传递不是源自那里的电子邮件到正确的电子邮件服务器。如果设置不正确,这将允许垃圾邮件发送者通过你的电子邮件系统进行循环攻击。但是,你可能知道涉及的IP地址,并可以将它们设置为允许列表中。 - Spencer Rathbun
如果您在购买的域名中有电子邮件,则它有自己的电子邮件服务器。您的“att”服务器只是设置为将其接收到的电子邮件转发到域名上的电子邮件。在这种情况下,要做的简单事情是从技术支持中找出托管您电子邮件的邮件服务器的名称。让他们知道您想使用smtp发送,并且他们应该能够指导您通过在服务器上打开smtp,然后只需用他们给您的名称替换服务器名称即可。我已经编辑了一个使用Google邮件的示例。 - Spencer Rathbun
在编程中,同时使用emailsmtplib是被Escualo在这个优秀的回答中推荐的。 - Colin D Bennett
5
如果不幸在公司的防火墙后面,你只能通过Outlook发送邮件。 - Prof. Falken
显示剩余5条评论

13
我想使用SMTPLIB发送电子邮件,这样更容易且不需要本地设置。由于其他答案没有直接帮助,这就是我所做的。
在浏览器中打开Outlook;转到右上角,单击设置的齿轮图标,从下拉列表中选择“选项”。 进入“帐户”,单击“Pop和Imap”, 您将看到选项:“让设备和应用程序使用pop”,
选择“是”选项并保存更改。
以下是代码;必要时进行编辑。 最重要的是启用POP和此处的服务器代码;
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

5
这种方法同样适用于使用smtp.office365.com的人。 - Weboide

8

使用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()

谢谢。这样做不会生成令人烦恼的Outlook错误消息吗? - user3262424
1
它可能会在较新版本的Windows上触发验证。不确定如何抑制它。我不再使用Windows了。 - Corey Goldberg

8

这是一个相对较旧的问题,但还有一种解决方案。当前Outlook SMTP服务器(截至2022年)为:

  • 主机: smtp.office365.com
  • 端口: 587 (用于TLS)

最简单和最清晰的解决方案可能是使用已经设置好这些内容的Red Mail

pip install redmail

那么:

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支持各种高级功能:

链接:

声明:我是作者


7

Office 365的简单解决方案是

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()

这里的df是一个转换为HTML表格的数据帧,正在被注入到html_template中。


ValueError: Protocol not provided to Api Component。不错的库,但我仍在努力找到如何验证代码的方法。 - wolfpan

2
这是我曾尝试在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()

1

-1
import pythoncom
import win32com.client

mail = win32com.client.Dispatch('outlook. Application', 
       pythoncom.CoInitialize())
ol_mail_item = 0x0
new_mail = mail.CreateItem(ol_mail_item)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接