6

Does anyone know how to add an email signature to an email using win32com?

import win32com.client as win32
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = 'TO'
mail.Subject = 'SUBJECT'
mail.HTMLbody = 'BODY'
mail.send
Nathan Davis
  • 5,636
  • 27
  • 39
Michael David
  • 93
  • 2
  • 2
  • 7

5 Answers5

10

A fully functional e-mailer function with signature included, using code from the answer above:

def Emailer(message, subject, recipient):
    import win32com.client as win32   

    outlook = win32.Dispatch('outlook.application')
    mail = outlook.CreateItem(0)
    mail.To = recipient
    mail.Subject = subject
    mail.GetInspector 

    index = mail.HTMLbody.find('>', mail.HTMLbody.find('<body')) 
    mail.HTMLbody = mail.HTMLbody[:index + 1] + message + mail.HTMLbody[index + 1:] 

    mail.Display(True)
    #mail.send #uncomment if you want to send instead of displaying

then call

Emailer("Hi there, how are you?", "Subject", "david@bisnode.com")
Vindictive
  • 311
  • 7
  • 19
David
  • 133
  • 1
  • 2
  • 11
  • In case you want to add an attachment you can add this to the code: if attachment != '': mail.Attachments.Add(attachment) – Chadee Fouad Apr 28 '21 at 17:33
6

Outlook signatures are not exposed through the Outlook Object Model. The best you can do is read the signature from the file system and add its contents to the HTML body appropriately. Keep in mind that two HTML strings must be merged, not just concatenated. You would also need to merge the styles from two HTML documents and take care of the embedded images used by the signature.

Note that Outlook adds a signature when an unmodified message is displayed or its inspector is touched

import win32com.client as win32
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = 'TO'
mail.Subject = 'SUBJECT'
mail.Display

mail.HTMLBody now contains the message signature that you will need to merger (not just concatenate!) with your own HTML

UPDATE: as of the latest (Summer 2016) builds of Outlook, GetInspector trick no longer works. Now Only MailItem.Display adds the signature to an unmodified message.
If you want to programmatically insert a signature, Redemption (I am its author) exposes RDOSignature object which implements ApplyTo method (it handles the signature image files and merges HTML styles appropriately).

Dmitry Streblechenko
  • 62,942
  • 4
  • 53
  • 78
  • That worked to get the signature in. Hopefully I am doing this right, but I added the following lines after mail.GetInspector: signiture = mail.HTMLbody and mail.HTMLbody = (r"""MESSAGE""") + signiture. Is that going to be the best way to merge the two items? I am new to Python, so I want to make sure I am using the correct method. – Michael David Aug 25 '15 at 18:39
  • No, you cannot concatenate 2 well formed HTML strings and end up with a well formed HTML string. - read the HTMLBody property (it will now include the signature), find the position of the "" character (this is to ensure you can work with a body element that has attributes), then insert your HTML string after that ">" character. – Dmitry Streblechenko Aug 25 '15 at 20:15
  • 1
    Thank you for walking me through that. I think I have it now. The formatting looks correct now, but please let me know if I am still doing something wrong. I added a message variable with my text and an index variable: __index = mail.HTMLbody.find('>', mail.HTMLbody.find(' – Michael David Aug 25 '15 at 21:14
2

You can find the signature in Outlook stored as an HTML file in %APPDATA%\Microsoft\Signatures and I used the following code to copy the file contents and add them to my email body

import win32com.client
import os 

     
    
signature_path = os.path.join((os.environ['USERPROFILE']),'AppData\Roaming\Microsoft\Signatures\Work_files\\') # Finds the path to Outlook signature files with signature name "Work"
html_doc = os.path.join((os.environ['USERPROFILE']),'AppData\Roaming\Microsoft\Signatures\Work.htm')     #Specifies the name of the HTML version of the stored signature
html_doc = html_doc.replace('\\\\', '\\') #Removes escape backslashes from path string


html_file = codecs.open(html_doc, 'r', 'utf-8', errors='ignore') #Opens HTML file and ignores errors
signature_code = html_file.read()               #Writes contents of HTML signature file to a string
signature_code = signature_code.replace('Work_files/', signature_path)      #Replaces local directory with full directory path
html_file.close()


olMailItem = 0x0
outlook = win32com.client.Dispatch("Outlook.Application")
newMail = outlook.CreateItem(olMailItem)

newMail.CC = "my@email.com"
newMail.Subject = subject
newMail.BodyFormat = 2 # olFormatHTML https://msdn.microsoft.com/en-us/library/office/aa219371(v=office.11).aspx
newMail.HTMLBody = "Email Message" + signature_code
newMail.display()

It seems I needed to replace the local path to the Signature files, with the absolute path in order to use images,etc.

sig_files_path = 'AppData\Roaming\Microsoft\Signatures\\' + signature_name + '_files\\'
    sig_html_path = 'AppData\Roaming\Microsoft\Signatures\\' + signature_name + '.htm'

    signature_path = os.path.join((os.environ['USERPROFILE']), sig_files_path) # Finds the path to Outlook signature files with signature name "Work"
    html_doc = os.path.join((os.environ['USERPROFILE']),sig_html_path)     #Specifies the name of the HTML version of the stored signature
    html_doc = html_doc.replace('\\\\', '\\')


    html_file = codecs.open(html_doc, 'r', 'utf-8', errors='ignore') #Opens HTML file and converts to UTF-8, ignoring errors
    signature_code = html_file.read()               #Writes contents of HTML signature file to a string

    signature_code = signature_code.replace((signature_name + '_files/'), signature_path)      #Replaces local directory with full directory path
    html_file.close()
  • I like what you've done here - I'm trying to do the same thing and can bring everything through and send successfully - I can't however get the image to render in the email - just the red 'X' and 'Pictures cannot be downloaded'. – Hatt Mar 05 '22 at 18:03
  • I did run into this problem myself, it seems I needed to replace the local path to the Signature files, with the absolute path – linktotherescue Mar 07 '22 at 04:51
0

you should be able to do this if your signature is set as default.

>>> signature = message.body
>>> message.body = "ahoj\n" + signature

You acan also use message.HTMLbody if your signature contains picture.

Your signature should always apear in the message if you set it as default. You will save current content of the body to signature variable and then add it to the end of the message. Works for me at least.

battle44
  • 55
  • 9
0

I started to apply the code that the good samaritan linktotherescue posted us above.

After doing research on the inspector feature I could make it by doing another signature at Outlook and changing the current image to a text called {IMAGE} then with "Find" I used to search the text and replaced with the image from my original signature.

import win32com.client as win32
import os
import codecs

sig_files_path "C://Users//RenterSa//AppData//Roaming//Microsoft//Signatures//Technical Support Engineer_archivos"
sig_html_path = "C://Users//RenterSa//AppData//Roaming//Microsoft//Signatures//TSE (Python).htm"
img_path = r'C:\Users\RenterSa\AppData\Roaming\Microsoft\Signatures\Technical Support Engineer_archivos\image001.jpg'

signature_path = os.path.join((os.environ['USERPROFILE']), sig_files_path) # Finds the path to Outlook signature files with signature name "Work"
html_doc = os.path.join((os.environ['USERPROFILE']),sig_html_path)     #Specifies the name of the HTML version of the stored signature
html_doc = html_doc.replace('\\\\', '\\')

html_file = codecs.open(html_doc, 'r', 'utf-8', errors='ignore') #Opens HTML file and converts to UTF-8, ignoring errors
signature_code = html_file.read()               #Writes contents of HTML signature file to a string

signature_code = signature_code.replace((sig_html_path + sig_files_path), 
signature_path)      #Replaces local directory with full directory path
html_file.close()

olMailItem = 0x0
outlook = win32.Dispatch("Outlook.Application")
newMail = outlook.CreateItem(olMailItem)

newMail.CC = "my@email.com"
newMail.Subject = "subject"
newMail.Importance = 2
newMail.BodyFormat = 3  # olFormatHTML https://msdn.microsoft.com/en-us/library/office/aa219371(v=office.11).aspx
newMail.HTMLBody = "Email Message" + signature_code
inspector = newMail.GetInspector
newMail.display()
doc = inspector.WordEditor
selection = doc.Content
selection.Find.Text = r"{IMAGE}"
selection.Find.Execute()
selection.Text = ""
img = selection.InlineShapes.AddPicture(img_path, 0 , 1)
Sachith Muhandiram
  • 2,819
  • 10
  • 45
  • 94