The main purpose is Daily mail creation work, monthly regular mail, etc. I wanted to streamline routine work.
The second purpose is Handling of json files in Python I wanted to learn how to work with Outlook. (Frankly, if you just mess with Outlook Putting data in Excel and creating it with VBA I think it's the most dressed up)
・ Think about the items in the json file -Create a class that handles json files -Create a class to handle Office Outlook -Development of main method to create mail by linking the above classes
・ Windows 10 -Python 3.7.0 ・ Office2016 ・ Other various libraries described in the code below
The class diagram created by pycharm looks like this.
As a requirement, -Format (text mail, HTML mail, rich text) ・ Sender ・ Destination (multiple can be specified) ・ CC (multiple specifications allowed) ・ BCC (multiple specifications allowed) ·subject ·Text ・ Attachment I wanted something that could be set It became like this.
mailSetting.json
{
"mailFormat": 3,
"senderAddress": "[email protected]",
"receiverAddressSet": ["[email protected]","[email protected]","[email protected]"],
"CC_AddressSet": ["[email protected]","[email protected]"],
"BCC_AddressSet": ["[email protected]","[email protected]"],
"title":"AIUEO",
"attachedFileFolderPath": "C:\\Users\\UserName\\Test",
"body": "〇〇\n\n Thank you for your hard work. It is 〇〇.\n\I will send you n〇〇.\n\n or more.\n"
}
Choose mailFormat from numbers 1 to 3 Each seems to correspond to [text mail, HTML mail or rich text].
JsonHandler.py
import json
class JsonHandler:
def __init__(self, jsonPath):
#Read json file
self.file = open(jsonPath, 'r', encoding="utf-8_sig")
self.jsonData = json.load(self.file)
#Primary nest json data acquisition
def getParam_OneNest(self, args):
return self.jsonData[args]
def __del__(self):
#File close
self.file.close()
I searched for an encoding method when importing a file, but I referred to this article. A story about having a hard time opening a file other than CP932 (Shift-JIS) encoded on Windows --Qiita
Apparently it is necessary to adopt the method of encoding = "utf-8_sig" for BOM processing.
OutlookHandler.py
import glob
import os
import win32com.client
class OutlookHandler:
def __init__(self):
self.outlook = win32com.client.Dispatch("Outlook.Application")
self.newMail = None
def create(self):
self.newMail = self.outlook.CreateItem(0)
def setting(self, argMailformat, argSenderaddress,
argReceiveraddressset, argCc_Addressset,
argBcc_Addressset, argTitle,
argAttachedfilefolderpath, argBody):
# ///Information setting for mail items
self.newMail.BodyFormat = argMailformat
try:
self.newMail._oleobj_.Invoke(*(64209, 0, 8, 0, self.outlook.Session.Accounts(argSenderaddress)))
except:
pass
self.newMail.To = argReceiveraddressset
self.newMail.cc = argCc_Addressset
self.newMail.Bcc = argBcc_Addressset
self.newMail.Subject = argTitle
#Add signature to body (only when Outlook starts)
try:
self.newMail.Body = argBody \
+ os.linesep \
+ self.newMail.GetInspector.WordEditor.Bookmarks('_MailAutoSig').Range.Text
except:
self.newMail.Body = argBody
#Get attachments
if os.path.isdir(argAttachedfilefolderpath):
for file in glob.glob(argAttachedfilefolderpath + '\\*'):
if os.path.isfile(file):
self.newMail.Attachments.Add(file)
def display(self):
self.newMail.Display(False)
def release(self):
self.newMail = None
self.outlook = None
I'm doing this strange way.
self.newMail._oleobj_.Invoke(*(64209, 0, 8, 0, self.outlook.Session.Accounts(argSenderaddress)))
It was a standard in the case of VBA The "SentOnBehalfOfName" field couldn't be used for some reason (though it may be a configuration problem on the outlook side). When I looked it up, I found an article like this, so I adopted it. https://stackoverflow.com/questions/35908212/python-win32com-outlook-2013-sendusingaccount-return-exception
However, this method assumes that the address set in json is registered as the user's address in outlook. If it is not registered, an exception will occur, so try catch is used. It does not mean that you can use something that is not registered, such as SentOnBehalfOfName. Therefore, there is room for improvement. (If you use only the default address, there is no problem)
self.newMail.Body = argBody \
+ os.linesep \
+ self.newMail.GetInspector.WordEditor.Bookmarks('_MailAutoSig').Range.Text #Signature the text
With the method using the fields of WordEditor.Bookmarks like this, There is a big problem that "* signature is given only when the outlook application is started". If you execute the main method while it is not running, an exception will occur.
Therefore, this time, process it with try catch, If it's not running, I'll give up signing.
This is also a part that can be improved, but it can't be helped (because the outlook startup process is quite annoying).
OutloookMailCreater.py
import datetime
import sys
#Reset module search path
#Make it possible to start by double-clicking
sys.path.append(r"C:\Users\UserName\PycharmProjects\CreateToolAndTest")
import os
import tkinter
from tkinter import messagebox
from PrivateTool.OutlookMailCreater.JsonHandler import JsonHandler
from PrivateTool.OutlookMailCreater.OutlookHandler import OutlookHandler
import traceback
if __name__ == '__main__':
try:
#message window preparation
root = tkinter.Tk()
root.withdraw()
root.attributes("-topmost", True)
#start outlook
outlookHandler = OutlookHandler()
outlookHandler.create()
#json file manipulation object
jsonHandler = JsonHandler(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'mailSetting.json'))
#Get the value from json and store it in the list
settingList = [jsonHandler.getParam_OneNest('mailFormat'), ]
settingList.append(jsonHandler.getParam_OneNest('senderAddress'))
tempSet = jsonHandler.getParam_OneNest('receiverAddressSet')
settingList.append('; '.join(tempSet))
tempSet = jsonHandler.getParam_OneNest('CC_AddressSet')
settingList.append('; '.join(tempSet))
tempSet = jsonHandler.getParam_OneNest('BCC_AddressSet')
settingList.append('; '.join(tempSet))
settingList.append(jsonHandler.getParam_OneNest('title'))
settingList.append(jsonHandler.getParam_OneNest('attachedFileFolderPath'))
settingList.append(jsonHandler.getParam_OneNest('body'))
#◆◆◆ If you want to add some processing to the list data, describe it here ◆◆◆
# myDate = datetime.date.today()
# if myDate.day < 16:
# myDate -= datetime.timedelta(days=15)
# settingList[5] = settingList[5].replace('$date', myDate.strftime('%Y%m'))
# ◆◆◆◆◆◆
#Create new email item in outlook
outlookHandler.setting(*settingList)
#View mail items
outlookHandler.display()
outlookHandler.release()
#announcement
messagebox.showinfo("", "Successful completion")
except:
print("Error", messagebox.showinfo("Error", "Error occurred"))
traceback.print_exc()
finally:
pass
It seems that you should set it as follows.
root.attributes("-topmost", True)
Click here for tools and source code ↓ CreateToolAndTest/Tool_Python/OutlookMailCreater at master · dede-20191130/CreateToolAndTest
Please comment if you have any supplements.
Recommended Posts