Insert String into Body of received email - vba

I wish to take the body of the selected received email (in folder view or as a selected email) and add an action stub to the beginning e.g.…
.Body = StubString & 'Body
I am uncertain how to use ActiveInspector and mailitem etc.
I have looked through the list of answered questions but I can't find one that will help me out.

Warnings:
Few of the emails I receive have a text body (property .Body) that I would wish to view or amend for someone else to view. Most have an html body (property .HTMLBody). If there is a text body, it is a crude simplification of the html body.
The email packages I use only show the text body if there is no html body. Amending the text body would have no effect on the display unless you delete the html body.
Between them, I believe the two answers and the macro below will give all the background you need to create your macro.
This answer of mine is a tutorial taking the reader through the Outlook Object model with the example macros you find most helpful. You should probably skip this now and come back later because I believe the second answer is closer to your requirement. Update excel sheet based on outlook mail
This second answer demonstrates how to create an Excel worksheet and copy selected properties of a mail item to it so the user can see what a mail item looks like to a VBA program. As written, the macro outputs details of every mail item in the Inbox. Comments within it, show how to limit the macro's output to selected emails so you can examine the content of the mail items you wish to amend. How to copy Outlook mail message into excel using VBA or Macros
Both the above answers examine all mail items in a selected folder. If you select a few mail items then run the macro below, you will get selected properties of those mail items.
Public Sub DemoExplorer()
Dim Exp As Outlook.Explorer
Dim ItemCrnt As MailItem
Dim NumSelected As Long
Set Exp = Outlook.Application.ActiveExplorer
NumSelected = Exp.Selection.Count
If NumSelected = 0 Then
Debug.Print "No emails selected"
Else
For Each ItemCrnt In Exp.Selection
With ItemCrnt
Debug.Print "--------------------------"
Debug.Print "From: " & .SenderName
Debug.Print "Subject: " & .Subject
Debug.Print "Received: " & Format(.ReceivedTime, "dMMMyy h:mm:ss")
'Debug.Print "Text " & Replace(Replace(Replace(.Body, vbLf, "{lf}"), vbCr, "{cr}"), vbTab, "{tb}")
'Debug.Print "Html " & Replace(Replace(Replace(.HTMLBody, vbLf, "{lf}"), vbCr, "{cr}"), vbTab, "{tb}")
End With
Next
End If
End Sub

Related

How do I create a script to remove the body of incoming emails?

I am trying to create a script that I can use with a message rule, to remove the body of incoming emails. Ideally I would like to leave the first 20 characters intact and delete the rest of the email, but I would settle for deleting the entire contents.
I thought this would be simple macro but I have found it impossible to achieve exactly what you requested; however, I have achieved something close. I have not deleted my diagnostic code so you can experiment yourself and perhaps discover a sequence of statements that I have not tried.
This is the macro that makes the changes:
Public Sub ReduceBody(ItemCrnt As Outlook.MailItem)
Dim ReducedBody As String
With ItemCrnt
' Not all items in Inbox are mail items. It should not be possible for
‘ a non-mail-item to reach this macro but check just in case.
If .Class = olMail Then
' I test for a particular subject and a particular sender
' Many properties of a mail item can be checked in this way. Adjust
' the If statement as necessary
If LCase(.Subject) = "attachments" And _
LCase(.SenderEmailAddress) = "xxxxx.com" Then
Debug.Print "Html: [" & Replace(Replace(.HtmlBody, vbLf, "{l}"), vbCr, "{r}") & "]"
Debug.Print "Text: [" & Replace(Replace(.Body, vbLf, "{l}"), vbCr, "{r}") & "]"
Debug.Print "Format: " & .BodyFormat
Debug.Assert False ' Have a look at the initial values of the properties
' Save reduced body because clearing the Html body also clears the text body
ReducedBody = Left$(.Body, 20)
.BodyFormat = olFormatPlain ' Set body format to plain text
.HtmlBody = "<BODY>" & ReducedBody & "</BODY>"
Debug.Print "Html: [" & .HtmlBody & "]"
Debug.Print "Text: [" & .Body & "]"
Debug.Print "Format: " & .BodyFormat
Debug.Assert False ' Have a look at the new values of the properties
.Close (olDiscard) ' Delete when the new
Exit Sub ‘ values are as you require
.Save ' Save amended mail item
End If
End If
End With
End Sub
I believe my comments explain the structure of the macro adequately.
Once the macro has confirmed that the item it has been passed is one it should process, it outputs the current values of the Html body, the text body and the body format to the Immediate Window and uses Debug.Assert to stop processing. Click F5 when you are ready to continue.
The code modifies these three properties, displays their new values and stops again.
I have known for a long time that Outlook will build a text body from an Html body but I had not realised how linked the Html body, the text body and the body format are. Changing any of them changes the others. The modification code I have provided, is the best I have been able to create which is:
Text body = first 20 characters of original text body
Html body = “” & first 20 characters of original text body & “”
Body format = Html
When you restart the macro with F5, the changes will be discarded. Unless the changes are discarded, they will be saved even if you do not execute the save command. Keep the discard statements until the values displayed are acceptable.
To test the above macro, I used:
Sub TestReduceBody()
Dim Exp As Explorer
Dim ItemCrnt As MailItem
Set Exp = Outlook.Application.ActiveExplorer
If Exp.Selection.Count = 0 Then
Call MsgBox("Please select one or more emails then try again", vbOKOnly)
Exit Sub
Else
For Each ItemCrnt In Exp.Selection
Call ReduceBody(ItemCrnt)
Next
End If
End Sub
I use a macro like this to test all my new mail-item, processing macros. Select one or more mail items and then start this macro. This macro allows me to start with a simple email and, only when that is processed correctly, do I try more complicated emails. I have several email addresses and I sent suitable test emails from a secondary account to my main account. You will have genuine emails ready to test. I highly recommend using macros like this.
Once you have amended the first macro to your requirements, set up a rule and link the rule to this macro. I assume you know how to create a rule, but I can provide instructions if necessary.

"Object required" when saving an email draft in Outlook VBA

I'm having issues saving a draft of a response to emails:
Dim fwdItem As Outlook.MailItem
Set fwdItem = item.ReplyAll
fwdItem.HTMLBody = "Looks Good." & vbCrLf & fwdItem.HTMLBody
fwdItem.SaveAs "C:\test.msg"
When it hits the "Save as" line, it gives me an Object Required error, but if it's instead fwdItem.Display, it works fine.
MSDN told me that it's usually due to using an variant as opposed to explicitly typing an object, but that's not what's going on here.
Try to explicitly specify the type (olMsg or olMsgUnicode when calling SaveAs.
Also do not concatenate two HTML strings - they must be merged.
How are you selecting the Mail Item?
This works on Outlook 2010
Option Explicit
Public Sub Example()
Dim Item As Outlook.MailItem
Set Item = ActiveExplorer.Selection.Item(1)
Debug.Print Item
Set Item = Item.ReplyAll
Debug.Print Item
Item.HTMLBody = "Looks Good." & vbCrLf & Item.HTMLBody
Item.SaveAs ("C:\Temp\test.msg"), olMsg
End Sub

Can I check if a recipient has an automatic reply before I send an email?

I have a macro set up that will automatically send out emails to dozens of managers. Sometimes they're away and I have to check the away message and manually forward it to the person covering for them.
I try to find a solution before I seek help so have mercy on me! I found a similar question but it wasn't a lot of help, I couldn't find a lot of info on extracting an auto response from a recipient in a draft.
So far this is what I've got:
Sub CheckAutoReply()
Dim OL As Outlook.Application
Dim EM As Outlook.MailItem
Dim R As Outlook.Recipient
Set OL = New Outlook.Application
Set EM = CreateItem(olMailItem)
With EM
.display
.To = "John.Doe#Stackoverflow.com" 'This is a recipient I know has an autoresponse. Fictitious of course.
End With
Set R = EM.Recipients(1) 'on hover it pops up with "EM.Recipients(1) = "John.Doe#Stackoverflow.com""
Debug.Print R.Name 'this returns "John.Doe#Stackoverflow.com"
Debug.Print R.AutoResponse 'this returns nothing
Set OL = Nothing
Set EM = Nothing
End Sub
This is not a proper answer but an attempt to get you started.
Your code suggests your knowledge of Outlook VBA is limited. If this is true, I doubt that any of the approaches in “a similar question” will be appropriate. Are you familiar with Visual Studio, C++, Delphi or Redemption? Even if you managed to access PR_OOF_STATE, you would not have the alternative email address.
I would start by attempting to extract the email address from the out-of-office reply. Looking for “#” and extracting the text back to and forward to the next space might be enough.
Copy the code below to an Outlook VBA module. Select one of the out-of-office replies and run macro DemoExplorer. The objective of this macro is to show you what the text and Html bodies of the email look like. Try this macro on other replies. Are the bodies consistent? Can you see how to extract the alternative email address?
Public Sub DemoExplorer()
Dim Exp As Outlook.Explorer
Dim ItemCrnt As MailItem
Dim NumSelected As Long
Set Exp = Outlook.Application.ActiveExplorer
NumSelected = Exp.Selection.Count
If NumSelected = 0 Then
Debug.Print "No emails selected"
Else
For Each ItemCrnt In Exp.Selection
With ItemCrnt
Debug.Print "From " & .SenderName & " Subject " & .Subject
Debug.Print "Text " & Replace(Replace(Replace(.Body, vbLf, "{lf}"), vbCr, "{cr}"), vbTab, "{tb}")
Debug.Print "Html " & Replace(Replace(Replace(.HTMLBody, vbLf, "{lf}"), vbCr, "{cr}"), vbTab, "{tb}")
End With
Next
End If
End Sub
The answer to the similar question you found (Remove recipients from Outlook email if automatic reply is activated) still stands. What were you having problem with?
The only additional possibility (and this is what Outlook uses when it displays an OOF banner for a recipient you are about to send to) is to use EWS and the GetMailTips operation (see https://msdn.microsoft.com/en-us/library/office/dd877060(v=exchg.150).aspx).

Outlook: Need to insert text and text variables into body of email reply based on selections from a custom form

My client service system sends email notifications when a new inquiry comes in. I am able to reply to the notification and the system will update the inquiry with information from my email reply.
Reply example:
To: "client inquiry system"
Subject: Re: I am having password trouble Inquiry:5601
Body of email below:
Your password has been reset.
The above will append "Your password has been reset." to the inquiries description.
I am also able to trigger changes to Status ( i.e. Closed, Resolved, Defunct) if I place special syntax at the top of the email body.
To: "client inquiry system"
Subject: Re: Inquiry:5601 -- I am having password trouble
Body of email below:
Status=Closed
Your password has been reset.
The above will set the inquiry to Closed in my system.
I would like to use a form or macro button that will provide users with drop down selections or free form text that will be added to the top of the email body once set.
I have some familiarity with VBA, but very new. Please help!
I am not convinced by your reply to my comment but this answer is an attempt to be helpful. It includes four macros that demonstrate functionality you will need. I hope it is enough to get you started.
When you open Outlook’s Visual Basic Editor, you will see something like the following down the left side of the screen. If you do not see it, click Ctrl+R.
- Project 1 (VbaProject.OTM)
- Microsoft Office Outlook Objects
ThisOutlookSession
- Modules
Module1
The hyphens will be in little boxes. If any hyphen is a plus, click the plus to expand the list under the heading.
Click ThisOutlookSession. You will get an empty code area on the right. This is like a module code area but is used for event routines. Copy this code into that area:
Option Explicit
Public WithEvents MyNewItems As Outlook.Items
Private Sub Application_Startup()
' This event routine is called when Outlook is started
Dim NS As NameSpace
Dim UserName As String
Set NS = CreateObject("Outlook.Application").GetNamespace("MAPI")
With NS
UserName = .CurrentUser
Set MyNewItems = .GetDefaultFolder(olFolderInbox).Items
End With
MsgBox "Welcome " & UserName
End Sub
Private Sub myNewItems_ItemAdd(ByVal Item As Object)
' This event routine is called each time an item is added to Inbox
' because of:
' Public WithEvents MyNewItems As Outlook.Items
' Set MyNewItems = .GetDefaultFolder(olFolderInbox).Items
With Item
Debug.Print "#####" & Format(Now(), "dMmmyy hh:mm:ss") & _
": Item added to Inbox with Subject: [" & .Subject & _
"] from [" & .SenderEmailAddress & "] with Text body"
Debug.Print .Body
End With
End Sub
Close Outlook and click Yes for “Do you want to save the VBA project ‘VbaProject.OTM?’”
Reopen Outlook. You will be told a program is trying to access email addresses. Click Allow access for, select 10 minutes and click Yes. You will get a window saying “Welcome John Doe”.
If this does not happen, select Tools then Macros then Security. Security level Medium must be selected to use macros safely.
The macro Application_Startup() has accessed Outlook’s email database. It is not easy to avoid the user being asked to allow access since Outlook has a very robust security system. There is a four step self-certification process which should allow you suppress this question for your own macros. I have successfully performed the first three steps but have never mastered the fourth step. I have carefully followed such instructions as I can find on the web but nothing has worked for me. Perhaps you will be more successful or perhaps you have access to an expert who can guide you if you want to suppress this question
The macro Application_Startup() has done two things: issued the welcome message and initialised MyNewItems. The welcome message is just a demonstration that you can access the user’s name which might be useful if you have a shared Inbox. Initialising MyNewItems activates the event routine myNewItems_ItemAdd(). This outputs details of the each new item to the Immediate Window.
This is a quick demonstration of event routines which I thought would be useful to you. However, I have discovered that if myNewItems_ItemAdd() is busy with one item when a second arrives, it is not called for the second item. I use a very old version of Outlook and this may be a bug that has been cleared in later releases. If you decide to use event routines, you need to check this out.
Another way of getting access to emails is Explorer. Insert a new module and copy the following code into it:
Option Explicit
Public Sub DemoExplorer()
Dim Exp As Outlook.Explorer
Dim ItemCrnt As MailItem
Dim NumSelected As Long
Set Exp = Outlook.Application.ActiveExplorer
NumSelected = Exp.Selection.Count
If NumSelected = 0 Then
Debug.Print "No emails selected"
Else
For Each ItemCrnt In Exp.Selection
With ItemCrnt
Debug.Print "From " & .SenderName & " Subject " & .Subject
End With
Next
End If
End Sub
DemoExplorer() shows another way of giving a macro access to mail items. The user selects one or more emails and then activates the macro DemoExplorer(). Again this just outputs some properties of a mail item to the Immediate Window.
Click F2 and the code window is replaced by a list of libraries. Scroll down the list of Classes and select MailItem. The right hand window displays all the members of MailItem. Some, such as ReceivedTime, are obvious but you will probably have to look up most. I suggest you make a note of all that look useful. Click a module, to get back to a code window when you have finished.
DemoReply(), below, is an updated version of DemoExplorer() which replies to selected emails. Add this code to your module:
Public Sub DemoReply()
Dim Exp As Outlook.Explorer
Dim ItemCrnt As MailItem
Dim Reply As MailItem
Dim Subject As String
Dim SenderAddr As String
Dim Received As Date
Set Exp = Outlook.Application.ActiveExplorer
If Exp.Selection.Count = 0 Then
Debug.Print "No emails selected"
Else
For Each ItemCrnt In Exp.Selection
' Get properties of message received
With ItemCrnt
Subject = .Subject
SenderAddr = .SenderEmailAddress
Received = .ReceivedTime
End With
' Create reply
Set Reply = CreateItem(olMailItem)
With Reply
.BodyFormat = olFormatPlain
.Body = "Thank you for your enquiry" & vbLf & _
" Subject: " & Subject & vbLf & _
" Received at: " & Format(Received, "d Mmm yyyy h:mm:ss") & vbLf & _
"which will be handled as soon as an analyst is available."
.Subject = "Thank you for your enquiry"
.Recipients.Add SenderAddr
' Display allows the user to review the reply before it is written to Outbox
' but control is not returned to this macro. Only the first select mail item
' will be processed
' Send gives the user no opportunity to review the replies but the macro does not
' use control so all replies are sent.
'.Display
.Send
End With
Next
End If
End Sub
I use an Outlook address for my private email and a Gmail address for my public email. I sent myself some text emails from the Gmail address. In Outlook, I selected these emails and activated DemoReply(). The expected replies arrived in my Gmail Inbox. Try sending yourself some emails and the try replying.
To demonstrate the use of a useform within Outlook, I inserted a new form and left the name as the default UserForm1. I dragged two text boxes to the form which I left with their default names of TextBox1 and TextBox2. I also dragged a command button which I renamed cmdSend.
An Outlook macro can only communicate with a user form via global variables. Add the following at the top of the module; they must be placed before any macros:
Public Box1 As String
Public Box2 As String
Add this macro to the module:
Sub DemoForm()
' Initialise global variables to be used by form before it is loaded
Box1 = "Initial value for text box1"
Box2 = "Initial value for text box2"
Load UserForm1
UserForm1.Show vbModal
' Control does not return to this module until user releases control of form
Debug.Print Box1
Debug.Print Box2
End Sub
Add this code to the form:
Private Sub cmdSend_Click()
Box1 = TextBox1
Box2 = TextBox2
Unload Me
End Sub
Private Sub UserForm_Initialize()
TextBox1 = Box1
TextBox2 = Box2
End Sub
Activate DemoForm(). The form will appear with the text boxes set to "Initial value for text box1" and "Initial value for text box2". Change these values and click Send. Control will be returned to DemoForm() which outputs the new values to the Immediate Window.

Retrieving Outlook Attachments in VBA from sent mail

What I am trying to get done is to have it so that on a few E-Mail templates we have at my job, when we drag and drop a certain Excel file to it, it will select and copy a range of that Excel file into the body of the email. My only question, as I've looked everywhere and all the code I've found seems to be for emails that are being received, not written, is how do I access:
The attachments in an email that I am writing
The body of the E-Mail I am writing
I'm sure I can get the code for everything else I want once I can get the attachments for the current Email.
Before any mentions "just record the macro and see how outlook does it" for some reason my outlook does not have a "record macro" item anywhere, as that was my first go-to as well.
how do I access: The attachments in an email that I am writing The
body of the E-Mail I am writing
Here is a very basic example. I have not done any error handling but I am sure you can take care of it.
Let's say the email that you are writing looks like this
All you need is this code
Sub Sample()
Dim NewMail As MailItem, oInspector As Inspector
Set oInspector = Application.ActiveInspector
'~~> Get the current open item
Set NewMail = oInspector.CurrentItem
With NewMail
Debug.Print .To
Debug.Print .subject
Debug.Print .Body
AttchCount = .Attachments.Count
If AttchCount > 0 Then
For I = 1 To AttchCount
'~~> Print Attachment names
Debug.Print .Attachments.Item(I).DisplayName
Next I
End If
End With
End Sub
Output