开发环境:centos7
基于:python3.5
调用库:tkinter smtplib email
linux中类outlook的GUI界面邮件发送程序,可以带附件,解决了windows中outlook不能添加linux中附件的问题。
当然有很多其他现成的程序可以实现类似的功能,本程序主要是基于练习使用python图形界面和smtplib/email库的目的。
mailSender.py
#!/usr/local/bin/python3.5 -u
import os
import re
from tkinter import *
from tkinter import messagebox
import smtplib
import email.mime.multipart
import email.mime.text
titleBarName = 'mailSender'
class sendMail:
def __init__(self):
self.smtp = smtplib.SMTP()
self.msg = email.mime.multipart.MIMEMultipart()
self.defaultEmailServerName = '163'
# Get the email you want to login.
def getEmailFrom(self, emailAddress):
self.emailAddress = emailAddress
# Get the password of the login email.
def getEmailPassword(self, password):
self.emailPassword = password
# Connect the smtp server, you can get the smtp server from the email.
def smtpConnect(self):
fromMatch = re.match('.*@(.*).com', self.emailAddress)
self.smtpServerName = fromMatch.group(1)
self.smtpServer = 'smtp.' + str(self.smtpServerName) + '.com'
self.defaultEmailServerName = self.smtpServerName
try:
self.smtp.connect(self.smtpServer)
self.smtp.ehlo()
print('*Info*: Connect to ' + str(self.smtpServer) + ' pass!')
return 0
except Exception as e:
print('*Error*: Failed to connect email server ' + self.smtpServer + ', ' + str(e))
messagebox.showerror(titleBarName, '*Error*: Failed to connect email server ' + self.smtpServer + ', ' + str(e))
return 1
# Login the smtp server, but notice that there is no need to login outlook email server.
def smtpLogin(self):
try:
self.smtp.login(self.emailAddress, self.emailPassword)
print('*Info*: login ' + str(self.emailAddress) + ' pass!')
return 0
except Exception as e:
print('*Error*: Failed to login smtp server ' + object.smtpServer + ', ' + str(e))
messagebox.showerror(titleBarName, '*Error*: Failed to login smtp server ' + object.smtpServer + ', ' + str(e))
return 1
# Specify the email receiver, the parameter "to" must be a string
def getEmailTo(self, to):
self.toString = ''
self.toList = []
for receiver in to.split():
if not re.match('.*@.*.com', receiver):
receiver = receiver + '@' + self.defaultEmailServerName + '.com'
self.toList.append(receiver)
if self.toString == '':
self.toString = receiver
else:
self.toString = self.toString + ' ' + receiver
# Subject is the email subject, it must be a string
def getEmailSubject(self, subject):
self.subject = subject
# Specify the email attach files, it must be a list
def getEmailAttach(self, attachFiles):
self.attachFiles = attachFiles
# Specify the email content
def getMsgContent(self, content):
self.content= email.mime.text.MIMEText(content)
self.msg.attach(self.content)
# Use MIMEText to add attach file
def msgAttach(self, attachFile):
attachFileName = os.path.basename(attachFile)
self.attach = email.mime.text.MIMEText(open(attachFile, 'rb').read(), 'base64', 'gb2312')
self.attach["Content-Type"] = 'application/octet-stream'
self.attach["Content-Disposition"] = 'attachment; filename="' + attachFileName + '"'
self.msg.attach(self.attach)
# It must specify "From", "To" and "Subject"
def msgConfig(self):
self.msg['From'] = self.emailAddress
print('*Info*: From : ' + self.msg['From'])
self.msg['To'] = self.toString
print('*Info*: To : ' + self.msg['To'])
self.msg['Subject'] = self.subject
print('*Info*: Subject : ' + self.msg['Subject'])
# For the email attach files, attach them one by one
def msgAttachs(self):
for attachFile in self.attachFiles:
if not re.match('^[ ]*$', attachFile):
self.msgAttach(attachFile)
# Quit the smtp connection
def smtpQuit(self):
print('*Info*: quit smtp connection.')
self.smtp.quit()
# Send mail
def smtpSendMail(self):
self.msgConfig()
self.msgAttachs()
try:
self.smtp.sendmail(self.emailAddress, self.toList, self.msg.as_string())
print('*Info*: Send email to ' + str(self.toString) + ' pass!')
messagebox.showinfo(titleBarName, 'Send email pass!')
return 0
except Exception as e:
print('*Error*: Failed to send email, ' + str(e))
messagebox.showerror(titleBarName, '*Error*: Failed to send email, ' + str(e))
return 1
class loginEmailGUI(object):
def __init__(self, object):
self.root = Tk()
self.root.geometry('800x600+200+200')
self.root.title(titleBarName)
# Label, "Email:"
self.emailAddressLabel = Label(self.root, text='Email:')
self.emailAddressLabel.grid(row=1, column=1, sticky=W, ipadx=20, ipady=10)
# Label, "Password:"
self.passwordLabel = Label(self.root, text='Password:')
self.passwordLabel.grid(row=2, column=1, sticky=W, ipadx=20, ipady=10)
# Entry, for "Email:", save the content on variable self.emailAddressEntryVar
self.emailAddressEntryVar = StringVar()
self.emailAddressEntry = Entry(self.root, textvariable=self.emailAddressEntryVar, bg='white')
self.emailAddressEntry.grid(row=1, column=2, sticky=W, ipadx=250, ipady=10)
# Entry, for "Password:", save the content on variable self.passwordEntryVar
self.passwordEntryVar = StringVar()
self.passwordEntry = Entry(self.root, textvariable=self.passwordEntryVar, show='*', bg='white')
self.passwordEntry.grid(row=2, column=2, sticky=W, ipadx=250, ipady=10)
# Button, "Login", click it to click the email server and login
self.loginButton = Button(self.root, text='Login', command=self.loginEmail, bg='blue')
self.loginButton.grid(row=3, column=2, ipadx=50, ipady=10)
self.root.mainloop()
# call class senMail to connet email server and login.
def loginEmail(self):
if re.match('^[ ]*$', self.emailAddressEntryVar.get().strip()):
print('*Error*: Email address cannot be empty!')
messagebox.showerror(titleBarName, '*Error*: Email address cannot be empty!')
return 1
elif not re.match('.*@.*.com', self.emailAddressEntryVar.get().strip()):
print('*Error*: Email format is wrong, it must be "***@***.com".')
messagebox.showerror(titleBarName, '*Error*: Email format is wrong, it must be "***@***.com".')
return 1
elif re.match('^[ ]*$', self.passwordEntryVar.get().strip()):
print('*Error*: Email password cannot be empty!')
messagebox.showerror(titleBarName, '*Error*: Email password cannot be empty!')
return 1
else:
object.getEmailFrom(self.emailAddressEntryVar.get().strip())
object.getEmailPassword(self.passwordEntryVar.get().strip())
if not object.smtpConnect():
if not object.smtpLogin():
object.smtpQuit()
self.root.destroy()
return 0
else:
object.smtpQuit()
return 1
else:
object.smtpQuit()
return 1
class sendEmailGUI(object):
def __init__(self, object):
self.root = Tk()
self.root.geometry('800x600+200+200')
self.root.title(titleBarName)
# Button, "Send", click it to execut sendMail.sendMail to send email
self.sendButton = Button(self.root, text='Send', command=self.sendMail, bg='blue')
self.sendButton.grid(row=1, rowspan=4, column=1, sticky=W, ipadx=10, ipady=50, padx=5, pady=5)
# Label, "From:"
self.fromLabel = Label(self.root, text='From:')
self.fromLabel.grid(row=1, column=2, sticky=W, ipadx=20, ipady=10)
# Label, "To:"
self.toLabel = Label(self.root, text='To:')
self.toLabel.grid(row=2, column=2, sticky=W, ipadx=20, ipady=10)
# Label, "Subject:"
self.subjectLabel = Label(self.root, text='Subject:')
self.subjectLabel.grid(row=3, column=2, sticky=W, ipadx=20, ipady=10)
# Label, "Attach:"
self.attachLabel = Label(self.root, text='Attach:')
self.attachLabel.grid(row=4, column=2, sticky=W, ipadx=20, ipady=10)
# Entry, for "From:", email address is saved on variable self.fromEntryVar, the default value is the email you login, but you can re-specify it.
self.fromEntryVar = StringVar()
self.fromEntry = Entry(self.root, textvariable=self.fromEntryVar, bg='white')
self.fromEntry.grid(row=1, column=3, sticky=W, ipadx=215, ipady=10)
self.fromEntryVar.set(object.emailAddress)
# Entry, for "To:", receiver list is saved on variable self.toEntryVar, you can specify several receivers, split them with space.
self.toEntryVar = StringVar()
self.toEntry = Entry(self.root, textvariable=self.toEntryVar, bg='white')
self.toEntry.grid(row=2, column=3, sticky=W, ipadx=215, ipady=10)
# Entry, from "Subject:", subject is saved on variable self.subjectEntryVar, it is the email title.
self.subjectEntryVar = StringVar()
self.subjectEntry = Entry(self.root, textvariable=self.subjectEntryVar, bg='white')
self.subjectEntry.grid(row=3, column=3, sticky=W, ipadx=215, ipady=10)
# Entry, from "Attach:", attach file list is saved on variable self.attachEntryVar, split them with space.
self.attachEntryVar = StringVar()
self.attachEntry = Entry(self.root, textvariable=self.attachEntryVar, bg='white')
self.attachEntry.grid(row=4, column=3, sticky=W, ipadx=215, ipady=10)
# Email content, get the content with self.contentText.get().
self.contentText = Text(self.root, bg='white')
self.contentText.grid(row=5, column=1, columnspan=3, sticky=W, ipadx=108, ipady=46)
# scrll bar
self.contentTextSbY = Scrollbar(self.root)
self.contentTextSbY.grid(row=5, column=4, sticky=W, ipadx=2, ipady=197)
self.contentText.configure(yscrollcommand=self.contentTextSbY.set)
self.contentTextSbY.configure(command=self.contentText.yview)
self.root.mainloop()
# Split receiver list to a list
# Split attach file list to a list
# Send email with sendMail.smtpSendMail
def sendMail(self):
# There must be at least one email receiver
if re.match('^[ ]*$', self.fromEntryVar.get().strip()):
print('*Error*: Email address cannot be empty!')
messagebox.showerror(titleBarName, '*Error*: Email address cannot be empty!')
return 1
# Check email format, it must be '.*@.*.com'
elif not re.match('.*@.*.com', self.fromEntryVar.get().strip()):
print('*Error*: Email format is wrong, it must be "***@***.com".')
messagebox.showerror(titleBarName, '*Error*: Email format is wrong, it must be "***@***.com".')
return 1
# Should not change the email from setting.
elif self.fromEntryVar.get().strip() != object.emailAddress:
print('*Error*: The send email is changed from "' + object.emailAddress + '" to "' + self.fromEntryVar.get().strip() + '", it may cause sending mail fail!')
messagebox.showerror(titleBarName, '*Error*: The send email is changed from "' + object.emailAddress + '" to "' + self.fromEntryVar.get().strip() + '", it may cause sending mail fail!')
return 1
# There must be at least one email receiver
elif re.match('^[ ]*$', self.toEntryVar.get().strip()):
print('*Error*: Email receiver list cannot be empty, you must specify at least one receiver!')
messagebox.showerror(titleBarName, '*Error*: Email receiver list cannot be empty, you must specify at least one receiver!')
return 1
# There must be email title
elif re.match('^[ ]*$', self.subjectEntryVar.get().strip()):
print('*Error*: Email subject cannot be empty!')
messagebox.showerror(titleBarName, '*Error*: Email subject cannot be empty!')
return 1
else:
object.getEmailFrom(self.fromEntryVar.get().strip())
object.getEmailTo(self.toEntryVar.get().strip())
object.getEmailSubject(self.subjectEntryVar.get().strip())
# If there is not attach file, set attachNewList first element to ' ', so sendMail will not attach any file.
attachList = self.attachEntryVar.get().strip()
attachNewList = []
if re.match('^[ ]*$', attachList):
attachNewList.append(' ')
else:
for attach in attachList.split():
if os.path.exists(attach):
attachNewList.append(attach)
else:
print('*Error*: ' + attach + ': No such file!')
messagebox.showerror(titleBarName, '*Error*: ' + attach + ': No such file!')
return 1
object.getEmailAttach(attachNewList)
# If email content is empty, set variable content to ' ', so sendMail will send an empty email.
content = self.contentText.get(1.0, END).strip()
if re.match('^[ ]*$', content):
content = ' '
object.getMsgContent(content)
# Call sendMail.sendMail to send email.
if not object.smtpConnect():
if not object.smtpLogin():
if not object.smtpSendMail():
object.smtpQuit()
self.root.destroy()
return 0
else:
object.smtpQuit()
return 1
else:
object.smtpQuit()
return 1
else:
object.smtpQuit()
return 1
def main():
object=sendMail()
if loginEmailGUI(object):
sendEmailGUI(object)
###################
## Main Function ##
###################
if __name__ == '__main__':
main()
实际使用如下图demo所示:
1. 登陆自己邮箱,输入帐号密码。
2. 输入相关内容,发件人,收件人,标题,附件地址,邮件内容。
3. 点击发送。
4. 去收件邮箱验证。
请注意这种使用方式主要是用于个人邮箱,比如163邮箱。如果想用自己outlook邮箱帐号来发送邮件,程序需要修改,因为outlook邮箱的协议和配置与我们常用的个人邮箱不太一样。