SydDevious
SydDevious

Reputation: 103

sending email via outlook using win32com and adding signature file

I am using Python 3.5 to automate some emails for work. We cannot use smtp. It must be done by controlling outlook via win32com. Ive got it all working. I can create an html email. I can give it an email address, and if its an active email address in the outlook profile thats open, it will send from that address. I can add a cc, a bcc, subject, etc.

My problem is adding the signature stored in outlook. I've read that outlook signatures arent exposed and therefore I cannot simply call them like I can the SendUsingAccount or mail.CC fields.

My alternative for this is to have the user specify the file using tkinter and askopenfilename().

that works for the most part. the user specifies the signature file location once. I store that in a data file that my tkinter program reads from upon start up. User generates the email and sends.

the problem is that I am reading the HTML from the signature file and storing that in a variable and then appending that to the existing HTMLBody.

It works. But any pictures included in the signature files HTML wont display.

Ive tried writing an additional script that will replace that short handed address of the picture within the html file to the FULL directory in hopes that would fix it. NO GO.

Is there any way to ensure that any pictures included in the signature file actually shows up in the email???

Here is my Signature file HTML reader/editor

def altersigfile(file):
    fullDir = file
    newDir = fullDir.rsplit("\\",1)[0]
    subDir = fullDir.rsplit("\\", 1)[1]
    subDir = subDir.replace(" ", "%20")
    subDir = subDir.strip(".htm")
    subDir += "_files"
    newDir += "/" + subDir
    newDir = newDir.replace("\\", "/")
    newsigfile = ""

    with open(fullDir,"r") as file:
        for line in file:

            if "src=" in line:
                check = ""
                newline = ""
                check = r'src="' + subDir
                newline = re.sub(subDir, newDir, line)
                newsigfile += newline

            else:
                newsigfile += line



    return newsigfile

Here is my emailer script:

def emailer(sendFrom, sendTo, subject, cc, bcc, body, sigfile=None,     auto=False, useSig=False):
ol = win32.Dispatch('Outlook.Application')
msg = ol.CreateItem(0)

#DO NOT CHANGE: the below script is the only way you were able to get outlook to register what email you give it. 
b=False
for i in range(1,ol.Session.Accounts.Count+1):

    if ol.Session.Accounts.Item(i).SmtpAddress == sendFrom:
        sendFrom = ol.Session.Accounts.Item(i)
        b=True
        break

if b==False:
    messagebox.showinfo("Invalid Address",
                        """The email address you entered ({email}), is not an authorized outlook email address. Please verify the email address you provided and make sure it is authorized in your outlook.""".format(email = sendFrom))
    return

msg._oleobj_.Invoke(*(64209, 0, 8, 0, sendFrom))
#end of DO NOT CHANGE

msg.To = sendTo
msg.Subject = subject

if cc:
    msg.CC = sendFrom

if bcc:
    msg.BCC = ol.Session.Accounts.Item(1).SmtpAddress

msg.HTMLBody = body


#currently this does add the sigfile html file held by outlook. However... the picture doesnt load. :(

if useSig==True:
    signature = altersigfile(sigfile)
    msg.HTMLBody += signature
    print(msg.HTMLBody)

So to reiterate. The above works in everyway except that the picture included in the signature file will not display. this is the only thing wrong and I cant seem to find a way to make it work. Any help would be greatly appreciated. thank you.

P.S. sorry for the formating in the second batch of code. For the life of me i couldnt seem to get it to format correctly.

Upvotes: 0

Views: 5706

Answers (2)

Dmitry Streblechenko
Dmitry Streblechenko

Reputation: 66245

A couple other options.

  1. Redemption (I am its author) exposes signatures through the RDOSession.Signatures collection and its RDOSignature object exposes ApplyTo method that copies the signature (text, images, styles) to the specified message.

  2. If all you want is the default signature, let Outlook do the job - the signature is added when Outlook displays the message (MailItem.Display) or when Outlook (prior to Outlook 2016) thinks you will display a message shortly by accessing the MailItem.GetInspector property. As soon as you call MailItem.Display or MailItem.GetInspector (pre-2016), as long as you have not yet set the message body using the Body or HTMLBody property, the message body will have the signature added. All you have to do now is read the HTMLBody property (which only has the signature), merge your text into that value, and set the HTMLBody property back. Note that you cannot simply concatenate two HTML strings, they must be merged.

Upvotes: 0

SydDevious
SydDevious

Reputation: 103

Just in case anyone is curious. This is how I did this in Idle:

import win32com.client as win32
import re
ol = win32.Dispatch('Outlook.Application')
msg = ol.CreateItem(0)
msg.GetInspector
bodystart = re.search("<body.*?>", msg.HTMLBody)
msg.HTMLBody = re.sub(bodystart.group(), bodystart.group()+"Hello this is a test body", msg.HTMLBody)

The key part here was the regular expressions. basically the following line:

bodystart = re.search("<body.*?>", msg.HTMLBody)

the above line of code lookes for an exact string of "body" followed by any amount of any charachter ".*" but not in a greedy fashion "?" then ending with ">" Once I had that I simply replaced that matched string with the matched string + whatever i want in my email body. g2g.

Upvotes: 2

Related Questions