How to send mail based on a draft then keep the draft? - vba

We are updating mails from the drafts folder and sending them a few times a day.
I want to open a selected mail resend it save it so it goes back to drafts and then close it.
I tried below
Sub DRAFT()
Dim myItem As Outlook.MailItem
Dim objInsp As Outlook.Inspector
Dim objActionsMenu As Office.CommandBarControl
Dim olResendMsg As Outlook.MailItem
' get current item & open if needed
On Error Resume Next
Select Case TypeName(Application.ActiveWindow)
Case "Explorer"
Set myItem = Application.ActiveExplorer.Selection.Item(1)
myItem.Display
Case "Inspector"
Set myItem = Application.ActiveInspector.CurrentItem
Case Else
End Select
On Error GoTo 0
If myItem Is Nothing Then
MsgBox "Could not use current item. Please select or open a single email.", _
vbInformation
GoTo exitproc
End If
' run the resend command
Set objInsp = myItem.GetInspector
objInsp.CommandBars.ExecuteMso ("ResendThisMessage")
' save orig email
myItem.Save
' close orig email
myItem.Close
exitproc:
Set myItem = Nothing
Set objInsp = Nothing
Set objActionsMenu = Nothing
Set olResendMsg = Nothing
End Sub

You need to pass a OlInspectorClose enumeration value to the MailItem.Close method. It indicates the close behavior, i.e. the save mode. If the item displayed within the inspector has not been changed, this argument has no effect.
Name Value Description
olDiscard 1 Changes to the document are discarded.
olPromptForSave 2 User is prompted to save documents.
olSave 0 Documents are saved.
So, your code should like that:
' close orig email
myItem.Close olSave
Instead of executing the ribbon control programmatically using the CommandBars.ExecuteMso method you may try to create a cope of the source item and then send it.
The ExecuteMso method is useful in cases where there is no object model for a particular command. Works on controls that are built-in buttons, toggleButtons and splitButtons. On failure it returns E_InvalidArg for an invalid idMso, and E_Fail for controls that are not enabled or not visible.
Instead, you may use the MailItem.Copy method which creates another instance of an object.
Sub CopyItem()
Dim myNameSpace As Outlook.NameSpace
Dim myFolder As Outlook.Folder
Dim myNewFolder As Outlook.Folder
Dim myItem As Outlook.MailItem
Dim myCopiedItem As Outlook.MailItem
Set myNameSpace = Application.GetNamespace("MAPI")
Set myFolder = myNameSpace.GetDefaultFolder(olFolderInbox)
Set myNewFolder = myFolder.Folders.Add("Saved Mail", olFolderDrafts)
Set myItem = Application.CreateItem(olMailItem)
myItem.Subject = "Speeches"
Set myCopiedItem = myItem.Copy
myCopiedItem.To = "email#address.com"
myCopiedItem.Send()
End Sub

Although there is a mistake in myItem.Close, you cannot resend mail that has not been sent.
Option Explicit
Sub SendMailBasedOnPermanentDraft()
Dim myItem As MailItem
Dim objInsp As Inspector
Dim myCopyOfUnsentItemInDrafts As MailItem
' get current item & open if needed
On Error Resume Next
Select Case TypeName(ActiveWindow)
Case "Explorer"
Set myItem = ActiveExplorer.Selection.Item(1)
Case "Inspector"
Set myItem = ActiveInspector.CurrentItem
Case Else
End Select
On Error GoTo 0
If myItem Is Nothing Then
MsgBox "Could not use current item. Please select or open a single email.", vbInformation
GoTo exitProc
End If
If myItem.Sent = False Then
Set myCopyOfUnsentItemInDrafts = myItem.copy
With myCopyOfUnsentItemInDrafts
.Subject = "Copied " & Now & ": " & myItem.Subject
.Save
.Display ' change to .Send
End With
Else
MsgBox "Select or open a single unsent email.", vbInformation
End If
exitProc:
Set myItem = Nothing
Set objInsp = Nothing
Set myCopyOfUnsentItemInDrafts = Nothing
End Sub

Related

Reply with .oft template and show images and attachments

When I create an email from an .oft template it doesn't show all the content of the e-mail.
It's missing content like images and/or attachments.
I tried to merge Sub reply1() and Sub reply2():
Sub Reply1()
Dim Original As Outlook.MailItem
Dim Reply As Outlook.MailItem
Set Original = Application.ActiveExplorer.Selection(1).Reply
Set Reply = Application.CreateItemFromTemplate("C:\Outlook\Mail.oft")
Original.HTMLBody = Reply.HTMLBody & Original.HTMLBody
Original.Display
End Sub
Sub Reply1()
This code doesn't show images or attachments of my own .oft mail.
It does show my e-mail signature but at the very bottom of both mails.
It does show the content of the e-mail I respond to correctly.
Sub Reply2()
Dim origEmail As MailItem
Dim replyEmail As MailItem
Set origEmail = ActiveExplorer.Selection(1)
Set replyEmail = CreateItemFromTemplate("C:\Outlook\Mail.oft")
replyEmail.To = origEmail.Reply.To
replyEmail.HTMLBody = replyEmail.HTMLBody & origEmail.Reply.HTMLBody
replyEmail.Recipients.ResolveAll
replyEmail.Display
Set origEmail = Nothing
Set replyEmail = Nothing
End Sub
Sub Reply2() does the opposite of Sub Reply1.
It shows the images and attachments of my own .oft mail.
It will not show my e-mail signature correctly.
It will not display the content of the mail I respond to correctly. The images are missing
Sub Reply1() Results:
Sub Reply2() Results
Embedded images are stored as hidden attachments on the email message. If you create a new Outlook item based on the template you need to re-attach the required images to get the message body rendered correctly. You can read more about that in the How to add an embedded image to an HTML message in Outlook 2010 thread.
Also, I have noticed the following code:
replyEmail.HTMLBody = replyEmail.HTMLBody & origEmail.Reply.HTMLBody
Remember, the HTML string should be a well-formed markup. If you want to insert something into the message body of an existing item you need to paste that inside the opening <body> and closing </body> elements. Otherwise, you may end up with a broken or improperly rendered message body. Even if Outlook do its great job by sorting most mistakes out.
The code below does work in my situation.
Sub Reply1()
Dim fromTemplate As MailItem
Dim reply As MailItem
Dim oItem As Object
Set fromTemplate = CreateItemFromTemplate("C:\Outlook\Mail.oft")
Set oItem = GetCurrentItem()
If Not oItem Is Nothing Then
Set reply = oItem.ReplyAll
CopyAttachments oItem, fromTemplate, reply
reply.HTMLBody = fromTemplate.HTMLBody & reply.HTMLBody
reply.Display
oItem.UnRead = False
End If
Set reply = Nothing
Set oItem = Nothing
End Sub
Function GetCurrentItem() As Object
Dim objApp As Outlook.Application
Set objApp = Application
On Error Resume Next
Select Case TypeName(objApp.ActiveWindow)
Case "Explorer"
Set GetCurrentItem = objApp.ActiveExplorer.Selection.Item(1)
Case "Inspector"
Set GetCurrentItem = objApp.ActiveInspector.CurrentItem
End Select
Set objApp = Nothing
End Function
Sub CopyAttachments(source1, source2, objTargetItem)
Set fso = CreateObject("Scripting.FileSystemObject")
Set fldTemp = fso.GetSpecialFolder(2) ' TemporaryFolder
strPath = fldTemp.Path & "\"
For Each objAtt In source1.Attachments
strFile = strPath & objAtt.fileName
objAtt.SaveAsFile strFile
objTargetItem.Attachments.Add strFile, , , objAtt.DisplayName
fso.DeleteFile strFile
Next
For Each objAtt In source2.Attachments
strFile = strPath & objAtt.fileName
objAtt.SaveAsFile strFile
objTargetItem.Attachments.Add strFile, , , objAtt.DisplayName
fso.DeleteFile strFile
Next
Set fldTemp = Nothing
Set fso = Nothing
End Sub
Forwarding an email retains attachments.
Option Explicit ' Consider this mandatory
' Tools | Options | Editor tab
' Require Variable Declaration
' If desperate declare as Variant
Sub Reply_Retain_Attachments()
Dim fromTemplate As MailItem
Dim origEmail As MailItem
Dim forwardEmail As MailItem
Set fromTemplate = CreateItemFromTemplate("C:\Outlook\Mail.oft")
Set origEmail = GetCurrentItem()
If Not origEmail Is Nothing Then
' Forward retains attachments
Set forwardEmail = origEmail.Forward
forwardEmail.HTMLBody = fromTemplate.HTMLBody & forwardEmail.HTMLBody
forwardEmail.To = origEmail.reply.To ' keep .reply here
forwardEmail.Recipients.ResolveAll
forwardEmail.Display
Else
' This may never occur
MsgBox "GetCurrentItem is nothing?"
End If
End Sub
Function GetCurrentItem() As Object
'On Error Resume Next ' uncomment if you find it necessary
Select Case TypeName(ActiveWindow)
Case "Explorer"
Set GetCurrentItem = ActiveExplorer.Selection.item(1)
Case "Inspector"
Set GetCurrentItem = ActiveInspector.CurrentItem
End Select
End Function

Delete automatic Signature from forwarded emails VBA macro

Newbie Outlook VBA. intermediate Excel VBA. Windows 7 Professional, Outlook 2010
I have a script running from a rule that autoforwards all incoming emails. I need it as a rule because otherwise it will not forward the mails in the queue when Outlook loads.
I would like to have the default signature deleted when the mails are forwarded. As the reply is "blank" it is unnecessary to have the sig appended. I have found some code that supposedly worked in Outlook 2007 from the MSDN site. It compiles no errors, executes no errors. I have referenced MS Word in VBA. But the forwarded emails all have the signature still attached.
I cannot just delete the signature because I need it to be there on replies. The switch for the signature is for both replies and forwarded mail.
Here is the code:
Option Explicit
Sub Incoming3(MyMail As MailItem)
Dim strID As String
Dim strSender As String
Dim StrSubject As String
Dim objItem As Outlook.MailItem
Dim myItem As Outlook.MailItem
strID = MyMail.entryID
Set objItem = Application.Session.GetItemFromID(strID)
strSender = objItem.SenderName
StrSubject = objItem.Subject
StrSubject = strSender + ": " + StrSubject
objItem.Subject = StrSubject
objItem.AutoForwarded = False
Set myItem = objItem.Forward
myItem.Recipients.Add "bcc.hwb#gmail.com"
myItem.DeleteAfterSubmit = True
Call DeleteSig(objItem)
myItem.Send
Set myItem = Nothing
Set objItem = Nothing
End Sub
Sub DeleteSig(msg As Outlook.MailItem)
Dim objDoc As Word.Document
Dim objBkm As Word.Bookmark
On Error Resume Next
Set objDoc = msg.GetInspector.WordEditor
Set objBkm = objDoc.Bookmarks("_MailAutoSig")
If Not objBkm Is Nothing Then
objBkm.Select
objDoc.Windows(1).Selection.Delete
End If
Set objDoc = Nothing
Set objBkm = Nothing
End Sub
Any help with Outlook or VBA code would be much appreciated.
Processing the wrong mail in DeleteSig.
myItem.DeleteAfterSubmit = True
Call DeleteSig(myItem)
myItem.Send
Edit 2015 02 26
Debugging VBA Code
Private Sub Incoming3_test()
' Open a mailitem then click F8 repeatedly from this code
Dim currItem As MailItem
Set currItem = ActiveInspector.currentItem
Incoming3 currItem
End Sub
Sub Incoming3(MyMail As MailItem)
Dim myItem As Outlook.MailItem
Set myItem = MyMail.Forward
myItem.Subject = MyMail.senderName & ": " & MyMail.Subject
myItem.Recipients.Add "bcc.hwb#gmail.com"
myItem.DeleteAfterSubmit = True
myItem.Display ' If you are using F8 you can
' view the action taken in DeleteSig.
' Delete the line later.
Call DeleteSig(myItem)
'myItem.Send
Set myItem = Nothing
End Sub
Sub DeleteSig(msg As Outlook.MailItem)
Dim objDoc As Word.Document
Dim objBkm As Word.Bookmark
On Error Resume Next '<--- Very bad without On Error GoTo 0
Set objDoc = msg.GetInspector.WordEditor
Set objBkm = objDoc.Bookmarks("_MailAutoSig")
On Error GoTo 0
If Not objBkm Is Nothing Then
objBkm.Select ' <--- This is where the action starts.
objDoc.Windows(1).Selection.Delete
End If
Set objDoc = Nothing
Set objBkm = Nothing
End Sub
Edit 2015 02 26 - End
When you assign a VBA macro sub to run by the rule you get an instance of the MailItem object. For example:
Sub Incoming3(MyMail As MailItem)
The MyMail object represents an incoming email message which you should use in the code. But I see that you get a new instance:
strID = MyMail.entryID
Set objItem = Application.Session.GetItemFromID(strID)
There is no need to do so. Use the MyMail object in the code.
Also I see the following code:
Set objBkm = objDoc.Bookmarks("_MailAutoSig")
Try to run the code under the debugger and see whether the bookmark can be found. If there is no such bookmark you need to search the body for the first entry From: in the text and delete all the content before that keyword.
Finally, you may find the Getting Started with VBA in Outlook 2010 article in MSDN helpful.

Need Error Message: Move To code

I have a Move to Code. The issue I am having is a result of multiple accounts. I have 3 to be exact.
Let's say - My boss emailed me, so I jump from my work account to my personal account. I read her email, jump back to my work account and run macro. It moves her (last read/selected) to location. I don't know how many personal emails I've moved by mistake because I forgot to reselect the correct email I meant to move.
How can I produce a prompt message stating I'm in the wrong account and if I should proceed? Note: there may be times I may need to proceed.
Additional Information:
Account One: Chieri Thompson (Personal)
Account Two: Artwork Emails
Account Three: DesignProofsTAC (work email - the one utilizing move to macro)
Under Design Proofs TAC is :
Inbox (folder)
Completed (subfolder)
Outsourced (subfolder)
.....
Private Sub CommandButton7_Click() 'COMPLETED
On Error Resume Next
Dim ns As Outlook.NameSpace
Dim MoveToFolder As Outlook.MAPIFolder
Dim objItem As Outlook.MailItem
Set objItem = objApp.ActiveInspector.CurrentItem
Set ns = Application.GetNamespace("MAPI")
Set MoveToFolder = ns.Folders("designproofstac").Folders("Inbox").Folders("3_COMPLETED")
If Application.ActiveExplorer.Selection.Count = 0 Then
MsgBox ("Not in Correct Folder")
Exit Sub
End If
' this is the error code I want to produce the "you are in wrong account - proceed anyway?" DesignProofsTAC should be "default" i guess.
If MoveToFolder Is Nothing Then
MsgBox "Target folder not found!", vbOKOnly + vbExclamation, "Move Macro Error"
End If
For Each objItem In Application.ActiveExplorer.Selection
If MoveToFolder.DefaultItemType = olMailItem Then
If objItem.Class = olMail Then
objItem.Move MoveToFolder
End If
End If
Next
Set objItem = Nothing
Set MoveToFolder = Nothing
Set ns = Nothing
End Sub
You may find this simpler than checking accounts.
Untested Code:
Option Explicit
Sub MoveOpenMail 'COMPLETED
' Place a button on the Quick Access Toolbar for an item opened for reading.
Dim ns As NameSpace
Dim MoveToFolder As Folder
Dim objItem As object ' <--- May not be a mailitem
Set ns = Application.GetNamespace("MAPI")
' Do not use On Error Resume Next
' unless there is a specific purpose
' and it is quickly followed by On Error GoTo 0
On Error Resume Next
Set MoveToFolder = ns.Folders("designproofstac").Folders("Inbox").Folders("3_COMPLETED")
On Error GoTo 0
If MoveToFolder Is Nothing Then
MsgBox "Target folder not found!", vbOKOnly + vbExclamation, "MoveOpenMail VBA Error"
GoTo ExitRoutine
End If
On Error Resume Next
Set objItem = ActiveInspector.CurrentItem
On Error GoTo 0
If objItem Is Nothing Then
MsgBox "Use this code when there is an open mailitem!", vbOKOnly + vbExclamation, "MoveOpenMail VBA Error"
GoTo ExitRoutine
End If
If MoveToFolder.DefaultItemType = olMailItem Then
If objItem.Class = olMail Then
objItem.Move MoveToFolder
End If
Else
MsgBox "Target folder is wrong type!", vbOKOnly + vbExclamation, "MoveOpenMail VBA Error"
End If
ExitRoutine:
Set ns = Nothing
Set MoveToFolder = Nothing
Set objItem = Nothing
End Sub
Sub MoveSelectedMail 'COMPLETED
' Place a button on the Quick Access Toolbar for an open folder
Dim ns As NameSpace
Dim MoveToFolder As Folder
Dim objItem as Object
Dim objExplorer As Explorer
Dim objSelection As Object
Dim x as Long
Set ns = Application.GetNamespace("MAPI")
On Error Resume Next
Set MoveToFolder = ns.Folders("designproofstac").Folders("Inbox").Folders("3_COMPLETED")
On Error GoTo 0
If MoveToFolder Is Nothing Then
MsgBox "Target folder not found!", vbOKOnly + vbExclamation, "MoveSelectedMail VBA Error"
GoTo ExitRoutine
End If
Set objExplorer = ActiveExplorer
Set objSelection = objExplorer.Selection
If objSelection.Count = 0 Then
MsgBox "Select one or more mailitems"
GoTo ExitRoutine
Else
If MoveToFolder.DefaultItemType = olMailItem Then
' Do not use For Each
' Count backwards when moving or deleting
For x = objSelection.Count to 1 step -1
Set objItem = objSelection.Item(x)
If objItem.Class = olMail Then
objItem.Move MoveToFolder
End If
Next x
Else
MsgBox "Target folder is wrong type!", vbOKOnly + vbExclamation, "MoveSelectedMail VBA Error"
End If
End If
ExitRoutine:
Set ns = Nothing
Set MoveToFolder = Nothing
Set objItem = Nothing
Set objExplorer = Nothing
Set objSelection = Nothing
End Sub
The Namespace class provides the Accounts property which eturns an Accounts collection object that represents all the Account objects in the current profile. The Account class provides the DeliveryStore property which returns a Store object that represents the default delivery store for the account. So, you can compare the Store where you chose the item and the default store for the account you need to move the item.
Also you may find the GetDefaultFolder method of the Store class helpful, it returns a Folder object that represents the default folder in the store and that is of the type specified by the FolderType argument. This method is similar to the GetDefaultFolder method of the NameSpace object. The difference is that this method gets the default folder on the delivery store that is associated with the account, whereas NameSpace.GetDefaultFolder returns the default folder on the default store for the current profile.

Inserting text into incoming email Outlook 2013 locked read only

I'm struggling to insert a string in an incoming email via VBA. The routine works fine when sending mail and it will work on incoming mail if the user clicks Actions Edit. The issue is that incoming mail is locked in read only mode. I've spent the past 13.5 hours searching everywhere. It is possible in earlier versions of Outlook, however Microsoft have removed the CommandBar functionality in Office 2013. Basically I need a way to allow the mail to be editable via a setting in VBA.
Here is the routine
Sub StampReference()
Dim objOL As Outlook.Application
Dim objNS As Outlook.NameSpace
Dim objDoc As Word.Document
Dim objSel As Word.Selection
strFullReference = "Reference: " & Reference
On Error Resume Next
Set objOL = Application
If objOL.ActiveInspector.EditorType = olEditorWord Then
Set objDoc = objOL.ActiveInspector.WordEditor
Set objNS = objOL.Session
Set objSel = objDoc.Windows(1).Selection
objSel.Move wdStory, -1
objDoc.Characters(1).InsertBefore _
strFullReference & vbCrLf & vbCrLf
objSel.Move wdParagraph, 1
End If
Set objOL = Nothing
Set objNS = Nothing
End Sub
EDIT
I've cracked it! Here is the way to change the mode for anyone interested. It is quick and dirty, however it shows how it can be done. I took some code that someone had written to do a Resend and played around with variants to stumble across the correct value to edit. I call this routine just before stamping the information in
Sub SetEditMode()
Dim myItem As Outlook.MailItem
Dim objInsp As Outlook.Inspector
Dim objActionsMenu As Office.CommandBarControl
Dim olNewMailItem As Outlook.MailItem
On Error Resume Next
Select Case TypeName(Application.ActiveWindow)
Case "Explorer"
Set myItem = ActiveExplorer.Selection.Item(1)
myItem.Display
Case "Inspector"
Set myItem = ActiveInspector.CurrentItem
Case Else
End Select
If myItem Is Nothing Then GoTo ExitProc
'edit mode
Set objInsp = ActiveInspector
objInsp.CommandBars.ExecuteMso ("EditMessage")
objActionsMenu.Execute
ExitProc:
End Sub
I've cracked it! Here is the way to change the mode for anyone interested. It is quick and dirty, however it shows how it can be done. I took some code that someone had written to do a Resend and played around with variants to stumble across the correct value to edit. I call this routine just before stamping the information in
Sub SetEditMode()
Dim myItem As Outlook.MailItem
Dim objInsp As Outlook.Inspector
Dim objActionsMenu As Office.CommandBarControl
Dim olNewMailItem As Outlook.MailItem
On Error Resume Next
Select Case TypeName(Application.ActiveWindow)
Case "Explorer"
Set myItem = ActiveExplorer.Selection.Item(1)
myItem.Display
Case "Inspector"
Set myItem = ActiveInspector.CurrentItem
Case Else
End Select
If myItem Is Nothing Then GoTo ExitProc
'edit mode
Set objInsp = ActiveInspector
objInsp.CommandBars.ExecuteMso ("EditMessage")
objActionsMenu.Execute
ExitProc:
End Sub
user2970334

Forward current message as attachment then delete original message

I get a lot of spam messages on my work Outlook 2010 account. I am provided with our spam blocker address to forward the spam (as an attachment) to.
I'd like to click on an icon on the ribbon (I already have this) and have VBA code run that takes the current message, attaches it to a new message, adds an address to the new message, sends the new message and then deletes the original message. (Deleting can be either putting the message in the "Deleted Items" folder or permanently deleting it.)
SOLVED!!!!
Here is code that does exactly what I want. I found it on the net and modified it to meet my needs.
Sub ForwardAndDeleteSpam()
'
' Takes currently highlighted e-mail, sends it as an attachment to
' spamfilter and then deletes the message.
'
Set objItem = GetCurrentItem()
Set objMsg = Application.CreateItem(olMailItem)
With objMsg
.Attachments.Add objItem, olEmbeddeditem
.Subject = "SPAM"
.To = "spamfilter#schools.nyc.gov"
.Send
End With
objItem.Delete
Set objItem = Nothing
Set objMsg = Nothing
End Sub
Function GetCurrentItem() As Object
On Error Resume Next
Select Case TypeName(Application.ActiveWindow)
Case "Explorer"
Set GetCurrentItem = Application.ActiveExplorer.Selection.Item(1)
Case "Inspector"
Set GetCurrentItem = Application.ActiveInspector.CurrentItem
Case Else
' anything else will result in an error, which is
' why we have the error handler above
End Select
Set objApp = Nothing
End Function
You can use this to go through a selection of emails, rather than just one by adapting the code as follows
Sub ForwardSpamToNetworkBox()
On Error Resume Next
Dim objItem As Outlook.MailItem
If Application.ActiveExplorer.Selection.Count = 0 Then
MsgBox ("No item selected")
Exit Sub
End If
For Each objItem In Application.ActiveExplorer.Selection
Set objMsg = Application.CreateItem(olMailItem)
With objMsg
.Attachments.Add objItem, olEmbeddeditem
.Subject = "SPAM"
.To = "spam#host.co.uk"
.Send
End With
objItem.Delete
Next
Set objItem = Nothing
Set objMsg = Nothing
End Sub
This was created with info from http://jmerrell.com/2011/05/21/outlook-macros-move-email
Ideally, instead of deleting, I'd move it to a subfolder called "Submitted" but I can't get that to work in Public Folders