How to add default signature in Outlook

匿名 (未验证) 提交于 2019-12-03 02:11:02

问题:

I am writing a VBA script in Access that creates and auto-populates a few dozen emails. It's been smooth coding so far, but I'm new to Outlook. After creating the mailitem object, how do I add the default signature to the email?

  1. This would be the default signature that is automatically added when creating a new email.

  2. Ideally, I'd like to just use ObjMail.GetDefaultSignature, but I can't find anything like it.

  3. Currently, I'm using the function below (found elsewhere on the internet) and referencing the exact path & filename of the htm file. But this will be used by several people and they may have a different name for their default htm signature file. So this works, but it's not ideal:

    Function GetBoiler(ByVal sFile As String) As String 'Dick Kusleika Dim fso As Object Dim ts As Object Set fso = CreateObject("Scripting.FileSystemObject") Set ts = fso.GetFile(sFile).OpenAsTextStream(1, -2) GetBoiler = ts.readall ts.Close End Function 

    (Called with getboiler(SigString = "C:\Users\" & Environ("username") & "\AppData\Roaming\Microsoft\Signatures\Mysig.txt"))

Edit

Thanks to JP (see comments), I realize that the default signature is showing up at first, but it disappears when I use HTMLBody to add a table to the email. So I guess my question is now: How do I display the default signature and still display an html table?

Sub X()     Dim OlApp As Outlook.Application     Dim ObjMail As Outlook.MailItem      Set OlApp = Outlook.Application     Set ObjMail = OlApp.CreateItem(olMailItem)      ObjMail.BodyFormat = olFormatHTML     ObjMail.Subject = "Subject goes here"     ObjMail.Recipients.Add "Email goes here"      ObjMail.HTMLBody = ObjMail.Body & "HTML Table goes here"     ObjMail.Display  End Sub 

回答1:

The code below will create an outlook message & keep the auto signature

Dim OApp As Object, OMail As Object, signature As String Set OApp = CreateObject("Outlook.Application") Set OMail = OApp.CreateItem(0)     With OMail     .Display     End With         signature = OMail.body     With OMail     '.To = "someone@somedomain.com"     '.Subject = "Type your email subject here"     '.Attachments.Add     .body = "Add body text here" & vbNewLine & signature     '.Send     End With Set OMail = Nothing Set OApp = Nothing 


回答2:

My solution is to display an empty message first (with default signature!) and insert the intended strHTMLBody into the existing HTMLBody.

If, like PowerUser states, the signature is wiped out while editing HTMLBody you might consider storing the contents of ObjMail.HTMLBody into variable strTemp immediately after ObjMail.Display and add strTemp afterwards but that should not be necessary.

Sub X(strTo as string, strSubject as string, strHTMLBody as string)     Dim OlApp As Outlook.Application       Dim ObjMail As Outlook.MailItem      Set OlApp = Outlook.Application    Set ObjMail = OlApp.CreateItem(olMailItem)     ObjMail.To = strTo    ObjMail.Subject = strSubject       ObjMail.Display    'You now have the default signature within ObjMail.HTMLBody.    'Add this after adding strHTMLBody    ObjMail.HTMLBody = strHTMLBody & ObjMail.HTMLBody     'ObjMail.Send 'send immediately or     'ObjMail.close olSave 'save as draft    'Set OlApp = Nothing  End sub 


回答3:

Outlook adds the signature to the new unmodified messages (you should not modify the body prior to that) when you call MailItem.Display (which causes the message to be displayed on the screen) or when you access the MailItem.GetInspector property - you do not have to do anything with the returned Inspector object, but Outlook will populate the message body with the signature.

Once the signature is added, read the HTMLBody property and merge it with the HTML string that you are trying to set. Note that you cannot simply concatenate 2 HTML strings - the strings need to be merged. E.g. if you want to insert your string at the top of the HTML body, look for the "<body" substring, then find the next occurrence of ">" (this takes care of the <body> element with attributes), then insert your HTML string after that ">".

Outlook Object Model does not expose signatures at all.

On a general note, the name of the signature is stored in the account profile data accessible through the IOlkAccountManager Extended MAPI interface. Since that interface is Extended MAPI, it can only be accessed using C++ or Delphi. You can see the interface and its data in OutlookSpy if you click the IOlkAccountManager button.
Once you have the signature name, you can read the HTML file from the file system (keep in mind that the folder name (Signatures in English) is localized.
Also keep in mind that if the signature contains images, they must also be added to the message as attachments and the <img> tags in the signature/message body adjusted to point the src attribute to the attachments rather than a subfolder of the Signatures folder where the images are stored.
It will also be your responsibility to merge the HTML styles from the signature HTML file with the styles of the message itself.

If using Redemption is an option, you can use its RDOAccount object (accessible in any language, including VBA). New message signature name is stored in the 0x0016001F property, reply signature is in 0x0017001F. You can also use the RDOAccount.ReplySignature and NewSignature properties.
Redemption also exposes RDOSignature.ApplyTo method that takes a pointer to the RDOMail object and inserts the signature at the specified location correctly merging the images and the styles:

set Session = CreateObject("Redemption.RDOSession") Session.MAPIOBJECT = Application.Session.MAPIOBJECT set Drafts = Session.GetDefaultFolder(olFolderDrafts) set   Msg = Drafts.Items.Add Msg.To =   "user@domain.demo" Msg.Subject =   "testing signatures" Msg.HTMLBody =   "<html><body>some <b>bold</b> message text</body></html>" set Account = Session.Accounts.GetOrder(2).Item(1)   'first mail account if  Not (Account  Is  Nothing)  Then    set Signature = Account.NewMessageSignature    if  Not (Signature  Is  Nothing)  Then     Signature.ApplyTo Msg,  false   'apply at the bottom    End If End If Msg.Send 

EDIT: as of July 2017, MailItem.GetInspector in Outlook 2016 no longer inserts the signature. Only MailItem.Display does.



回答4:

Dim OutApp As Object, OutMail As Object, LogFile As String Dim cell As Range, S As String, WMBody As String, lFile As Long  S = Environ("appdata") & "\Microsoft\Signatures\" If Dir(S, vbDirectory) <> vbNullString Then S = S & Dir$(S & "*.htm") Else S = "" S = CreateObject("Scripting.FileSystemObject").GetFile(S).OpenAsTextStream(1,  -2).ReadAll  WMBody = "<br>Hi All,<br><br>" & _          "Last line,<br><br>" & S 'Add the Signature to end of HTML Body 

Just thought I'd share how I achieve this. Not too sure if it's correct in the defining variables sense but it's small and easy to read which is what I like.

I attach WMBody to .HTMLBody within the object Outlook.Application OLE.

Hope it helps someone.

Thanks, Wes.



回答5:

I have made this a Community Wiki answer because I could not have created it without PowerUser's research and the help in earlier comments.

I took PowerUser's Sub X and added

Debug.Print "n------"    'with different values for n Debug.Print ObjMail.HTMLBody 

after every statement. From this I discovered the signature is not within .HTMLBody until after ObjMail.Display and then only if I haven't added anything to the body.

I went back to PowerUser's earlier solution that used C:\Users\" & Environ("username") & "\AppData\Roaming\Microsoft\Signatures\Mysig.txt"). PowerUser was unhappy with this because he wanted his solution to work for others who would have different signatures.

My signature is in the same folder and I cannot find any option to change this folder. I have only one signature so by reading the only HTM file in this folder, I obtained my only/default signature.

I created an HTML table and inserted it into the signature immediately following the <body> element and set the html body to the result. I sent the email to myself and the result was perfectly acceptable providing you like my formatting which I included to check that I could.

My modified subroutine is:

Sub X()    Dim OlApp As Outlook.Application   Dim ObjMail As Outlook.MailItem    Dim BodyHtml As String   Dim DirSig As String   Dim FileNameHTMSig As String   Dim Pos1 As Long   Dim Pos2 As Long   Dim SigHtm As String    DirSig = "C:\Users\" & Environ("username") & _                                "\AppData\Roaming\Microsoft\Signatures"    FileNameHTMSig = Dir$(DirSig & "\*.htm")    ' Code to handle there being no htm signature or there being more than one    SigHtm = GetBoiler(DirSig & "\" & FileNameHTMSig)   Pos1 = InStr(1, LCase(SigHtm), "<body")    ' Code to handle there being no body    Pos2 = InStr(Pos1, LCase(SigHtm), ">")    ' Code to handle there being no closing > for the body element     BodyHtml = "<table border=0 width=""100%"" style=""Color: #0000FF""" & _          " bgColor=#F0F0F0><tr><td align= ""center"">HTML table</td>" & _          "</tr></table><br>"   BodyHtml = Mid(SigHtm, 1, Pos2 + 1) & BodyHtml & Mid(SigHtm, Pos2 + 2)    Set OlApp = Outlook.Application   Set ObjMail = OlApp.CreateItem(olMailItem)   ObjMail.BodyFormat = olFormatHTML   ObjMail.Subject = "Subject goes here"   ObjMail.Recipients.Add "my email address"   ObjMail.Display  End Sub 

Since both PowerUser and I have found our signatures in C:\Users\" & Environ("username") & "\AppData\Roaming\Microsoft\Signatures I suggest this is the standard location for any Outlook installation. Can this default be changed? I cannot find anything to suggest it can. The above code clearly needs some development but it does achieve PowerUser's objective of creating an email body containing an HTML table above a signature.



回答6:

I figured out a way, but it may be too sloppy for most. I've got a simple Db and I want it to be able to generate emails for me, so here's the down and dirty solution I used:

I found that the beginning of the body text is the only place I see the "<div class=WordSection1>" in the HTMLBody of a new email, so I just did a simple replace, replacing

"<div class=WordSection1><p class=MsoNormal><o:p>"

with

"<div class=WordSection1><p class=MsoNormal><o:p>" & sBody

where sBody is the body content I want inserted. Seems to work so far.

.HTMLBody = Replace(oEmail.HTMLBody, "<div class=WordSection1><p class=MsoNormal><o:p>", "<div class=WordSection1><p class=MsoNormal><o:p>" & sBody) 


回答7:

I constructed this approach while looking for how to send a message on a recurring schedule. I found the approach where you reference the Inspector property of the created message did not add the signature I wanted (I have more than one account set up in Outlook, with separate signatures.)

The approach below is fairly flexible and still simple.

    Private Sub Add_Signature(ByVal addy as String, ByVal subj as String, ByVal body as String)        Dim oMsg As MailItem        Set oMsg = Application.CreateItem(olMailItem)        oMsg.To = addy        oMsg.Subject = subj        oMsg.Body = body        Dim sig As String        ' Mysig is the name you gave your signature in the OL Options dialog         sig = ReadSignature("Mysig.htm")        oMsg.HTMLBody = Item.Body & "<p><BR/><BR/></p>" & sig ' oMsg.HTMLBody        oMsg.Send        Set oMsg = Nothing     End Sub      Private Function ReadSignature(sigName As String) As String        Dim oFSO, oTextStream, oSig As Object        Dim appDataDir, sig, sigPath, fileName As String        appDataDir = Environ("APPDATA") & "\Microsoft\Signatures"        sigPath = appDataDir & "\" & sigName         Set oFSO = CreateObject("Scripting.FileSystemObject")        Set oTextStream = oFSO.OpenTextFile(sigPath)        sig = oTextStream.ReadAll        ' fix relative references to images, etc. in sig        ' by making them absolute paths, OL will find the image        fileName = Replace(sigName, ".htm", "") & "_files/"        sig = Replace(sig, fileName, appDataDir & "\" & fileName)        ReadSignature = sig     End Function 


回答8:

I need 50 rep to post a comment against the Signature Option I found most helpful, however I had an issue with images not showing correctly so I had to find a work around. This is my solution:

Using @Morris Maynard's answer as a base https://stackoverflow.com/a/18455148/2337102 I then had to go through the following:

Notes:
Back up your .htm file before starting, copy & paste to a secondary folder

  1. You will be working with both the SignatureName.htm and the SignatureName_files Folder

  2. You do not need HTML experience, the files will open in an editing program such as Notepad or Notepad++ or your specified HTML Program

  3. Navigate to your Signature File location (standard should be C:\Users\"username"\AppData\Roaming\Microsoft\Signatures)

  4. Open the SignatureName.htm file in a text/htm editor (right click on the file, "Edit with Program")

  5. Use Ctrl+F and enter .png; .jpg or if you don't know your image type, use image001 You will see something like: src="signaturename_files/image001.png"

  6. You need to change that to the whole address of the image location C:\Users\YourName\AppData\Roaming\Microsoft\Signatures\SignatureNameFolder_files\image001
    or
    src="E:\location\Signatures\SignatureNameFolder_files\image001.png"

  7. Save your file (overwrite it, you had of course backed up the original)

  8. Return to Outlook and Open New Mail Item, add your signature. I received a warning that the files had been changed, I clicked ok, I needed to do this twice, then once in the "Edit Signatures Menu".

    Some of the files in this webpage aren't in the expected location. Do you want to download them anyway? If you're sure the Web page is from a trusted source, click Yes."

  9. Run your Macro event, the images should now be showing.

Credit
MrExcel - VBA code signature code failure: http://bit.ly/1gap9jY



回答9:

Most of the other answers are simply concatenating their HTML body with the HTML signature. However, this does not work with images, and it turns out there is a more "standard" way of doing this.1

Microsoft Outlook pre-2007 which is configured with WordEditor as its editor, and Microsoft Outlook 2007 and beyond, use a slightly cut-down version of the Word Editor to edit emails. This means we can use the Microsoft Word Document Object Model to make changes to the email.

Set objMsg = Application.CreateItem(olMailItem) objMsg.GetInspector.Display 'Displaying an empty email will populate the default signature Set objSigDoc = objMsg.GetInspector.WordEditor Set objSel = objSigDoc.Windows(1).Selection With objSel    .Collapse wdCollapseStart    .MoveEnd WdUnits.wdStory, 1    .Copy 'This will copy the signature End With objMsg.HTMLBody = "<p>OUR HTML STUFF HERE</p>" With objSel    .Move WdUnits.wdStory, 1 'Move to the end of our new message    .PasteAndFormat wdFormatOriginalFormatting 'Paste the copied signature End With  'I am not a VB programmer, wrote this originally in another language so if it does not 'compile it is because this is my first VB method :P 

Microsoft Outlook 2007 Programming (S. Mosher)> Chapter 17, Working with Item Bodies: Working with Outlook Signatures



回答10:

I like Mozzi's answer but found that it did not retain the default fonts that are user specific. The text all appeared in a system font as normal text. The code below retains the user's favourite fonts, while making it only a little longer. It is based on Mozzi's approach, uses a regular expression to replace the default body text and places the user's chosen Body text where it belongs by using GetInspector.WordEditor. I found that the call to GetInspector did not populate the HTMLbody as dimitry streblechenko says above in this thread, at least, not in Office 2010, so the object is still displayed in my code. In passing, please note that it is important that the MailItem is created as an Object, not as a straightforward MailItem - see here for more. (Oh, and sorry to those of different tastes, but I prefer longer descriptive variable names so that I can find routines!)

Public Function GetSignedMailItemAsObject(ByVal ToAddress As String, _                       ByVal Subject As String, _                       ByVal Body As String, _                       SignatureName As String) As Object '================================================================================================================='Creates a new MailItem in HTML format as an Object. 'Body, if provided, replaces all text in the default message. 'A Signature is appended at the end of the message. 'If SignatureName is invalid any existing default signature is left in place. '================================================================================================================= ' REQUIRED REFERENCES ' VBScript regular expressions (5.5) ' Microsoft Scripting Runtime '================================================================================================================= Dim OlM As Object               'Do not define this as Outlook.MailItem.  If you do, some things will work and some won't (i.e. SendUsingAccount) Dim Signature As String Dim Doc As Word.Document Dim Regex As New VBScript_RegExp_55.RegExp       '(can also use use Object if VBScript is not Referenced)  Set OlM = Application.CreateItem(olMailItem) With OlM     .To = ToAddress     .Subject = Subject     'SignatureName is the exactname that you gave your signature in the Message>Insert>Signature Dialog     Signature = GetSignature(SignatureName)     If Signature <> vbNullString Then '        Should really strip the terminal </body tag out of signature by removing all characters from the start of the tag '        but Outlook seems to handle this OK if you don't bother.         .Display                                'Needed.  Without it, there is no existing HTMLbody available to work with.         Set Doc = OlM.GetInspector.WordEditor   'Get any existing body with the WordEditor and delete all of it         Doc.Range(Doc.Content.Start, Doc.Content.End) = vbNullString 'Delete all existing content - we don't want any default signature         'Preserve all local email formatting by placing any new body text, followed by the Signature, into the empty HTMLbody.         With Regex             .IgnoreCase = True                  'Case insensitive             .Global = False                     'Regex finds only the first match             .MultiLine = True                   'In case there are stray EndOfLines (there shouldn't be in HTML but Word exports of HTML can be dire)             .Pattern = "(<body.*)(?=<\/body)"   'Look for the whole HTMLbody but do NOT include the terminal </body tag in the value returned             OlM.HTMLbody = .Replace(OlM.HTMLbody, "$1" & Signature)         End With ' Regex         Doc.Range(Doc.Content.Start, Doc.Content.Start) = Body 'Place the required Body before the signature (it will get the default style)         .Close olSave                           'Close the Displayed MailItem (actually Object) and Save it.  If it is left open some later updates may fail.     End If ' Signature <> vbNullString End With ' OlM Set GetSignedMailItemAsObject = OlM End Function  Private Function GetSignature(sigName As String) As String Dim oTextStream As Scripting.TextStream Dim oSig As Object Dim appDataDir, Signature, sigPath, fileName As String Dim FileSys As Scripting.FileSystemObject        'Requires Microsoft Scripting Runtime to be available     appDataDir = Environ("APPDATA") & "\Microsoft\Signatures"     sigPath = appDataDir & "\" & sigName & ".htm"     Set FileSys = CreateObject("Scripting.FileSystemObject")     Set oTextStream = FileSys.OpenTextFile(sigPath)     Signature = oTextStream.ReadAll     ' fix relative references to images, etc. in Signature     ' by making them absolute paths, OL will find the image     fileName = Replace(sigName, ".htm", "") & "_files/"     Signature = Replace(Signature, fileName, appDataDir & "\" & fileName)     GetSignature = Signature End Function 


回答11:

Often this question is asked in the context of Ron de Bruin's RangeToHTML function, which creates an HTML PublishObject from an Excel.Range, extracts that via FSO, and inserts the resulting stream HTML in to the email's HTMLBody. In doing so, this removes the default signature (the RangeToHTML function has a helper function GetBoiler which attempts to insert the default signature).

Unfortunately, the poorly-documented Application.CommandBars method is not available via Outlook:

wdDoc.Application.CommandBars.ExecuteMso "PasteExcelTableSourceFormatting" 

It will raise a runtime 6158:

But we can still leverage the Word.Document which is accessible via the MailItem.GetInspector method, we can do something like this to copy & paste the selection from Excel to the Outlook email body, preserving your default signature (if there is one).

Dim rng as Range Set rng = Range("A1:F10") 'Modify as needed  With OutMail     .To = "xxxxx@xxxxx.com"     .BCC = ""     .Subject = "Subject"     .Display     Dim wdDoc As Object     '## Word.Document     Dim wdRange As Object   '## Word.Range     Set wdDoc = OutMail.GetInspector.WordEditor     Set wdRange = wdDoc.Range(0, 0)     wdRange.InsertAfter vbCrLf & vbCrLf     'Copy the range in-place     rng.Copy     wdRange.Paste End With 

Note that in some cases this may not perfectly preserve the column widths or in some instances the row heights, and while it will also copy shapes and other objects in the Excel range, this may also cause some funky alignment issues, but for simple tables and Excel ranges, it is very good:



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!