Open email after sending - vba

Why am I facing the below problem?
I have written a code to open sent email after sending email. The VBA code doesn't open the latest sent email but the previous one.
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim myItem As MailItem
Dim myNamespace As NameSpace
Dim myFolder As Folder
Set myNamespace = Application.GetNamespace("MAPI")
Set myFolder = myNamespace.GetDefaultFolder(olFolderSentMail)
Set myItem = myFolder.Items(myFolder.Items.Count)
myItem.Display
End Sub

This is the answer why this won't work with the Application_ItemSend event:
Application_ItemSend is called before the email is sent. You can see that because it has a Cancel parameter. This means the email only gets sent if Cancel = False else the email is dropped.
So you just cannot display the email because it isn't sent at this time in the Application_ItemSend event. It gets sent after the Application_ItemSend is finished.
Note: If you put a break point within the Application_ItemSend you will see that the "New Email" window remains open/visible until the ItemSend event is finished. Therefore you cannot open that email within that event.
Workaround
You might try the following code. This creates an event for the default folder of sent items which is called when an item is added to this folder.
A restart of Outlook might be needed after adding the code (or at least running the Application_Startup procedure once).
Option Explicit
Public WithEvents myOlItems As Outlook.Items
Private Sub Application_Startup()
Set myOlItems = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderSentMail).Items
End Sub
Private Sub myOlItems_ItemAdd(ByVal Item As Object)
Item.Display
End Sub
If the folder where your sent items are moved to is not the default Outlook sent mail folder then you need to find the right folder to set it in Application_Startup.

Related

How to forward email after sending?

I use Application_ItemSend to trigger a userform with some inputs, then I want to forward the email using some of those inputs.
What I'm currently doing works if I send a new email rather than forward the original. I assume the original email is not sent until the ItemSend macro finishes and I can't forward an email that hasn't been sent yet.
How can I write a macro that will run after the email is sent?
You are on the right avenue - you need to wait until the item is sent out. Typically Outlook puts sent items to the Sent Items folder, so you can hook up the ItemAdd event on the Sent Items folder and forward the original sent email.
Public WithEvents myOlItems As Outlook.Items
Public Sub Initialize_handler()
Set myOlItems = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderSentMail).Items
End Sub
Private Sub myOlItems_ItemAdd(ByVal Item As Object)
Dim myOlMItem As Outlook.MailItem
myOlMItem = Item.Forward()
myOlMItem.Recipients.Add "Eugene Astafiev"
myOlMItem.Send
End Sub
Note, users or other add-ins (VBA macros) can set up a custom folder for keeping sent items in Outlook. In that case you need to check out the MailItem.SaveSentMessageFolder property which returns or sets a Folder object that represents the folder in which a copy of the email message will be saved after being sent. So, you need to set up a hook on that folder too. You can do that in the ItemSend event handler.

How to execute a code after mail has been sent?

I'm trying to record a specific next-numbering on certain e-mails after I send them. However Application_ItemSend executes the code before it sends the e-mail.
I'm adding a reference number to the Subject, but I don't want to confuse everyone with random numbers appearing in their inbox.
Is there a way to execute code after the send?
I think I got it:
Declare a new type of events-related variable to ensure every time an e-mail is added to the "Received Items" folder an action is executed.
Private WithEvents Rcvditems As Outlook.Items
The method I used to avoid variables being restored to 'nothing' is using the same Application.Item_Send event. This option will ensure I activate my reader every time I send an e-mail.
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set Rcvditems = objNS.GetDefaultFolder(olFolderSentMail).Items
End Sub
... what it is doing is recalculating my variable 'Rcvditems'.
Finally, as Rcvd_Items is an event-related variable, I can assign event 'AddItem' to it.
Private Sub Rcvditems_ItemAdd(ByVal Item As Object)
On Error GoTo EscapeSub
Call MyMacro(Item)
EscapeSub:
End Sub
Like this I'm ensuring that I won't alter the e-mail when prior sending it, but just the e-mail that is added in the Received-Items folder.
By default, the sent items are placed to the Sent Items folder in Outlook. If so, you can hook to the ItemAdd event of the Items class which belongs to the Sent Items folder. It is fired when one or more items are added to the specified collection. This event does not run when a large number of items are added to the folder at once (more than sixteen) - this is a known issue in OOM and exists in all Outlook versions.
Public WithEvents myOlItems As Outlook.Items
Public Sub Initialize_handler()
Set myOlItems = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderSentItems).Items
End Sub
Private Sub myOlItems_ItemAdd(ByVal Item As Object)
MsgBox Item.Subject
End Sub
Note, the MailItem.SaveSentMessageFolder property allows to set a Folder object that represents the folder in which a copy of the email message will be saved after being sent. So, it is not necessary that an Outlook item will be saved to the Sent Items folder if an add-in sets this property in the ItemSend event handler.

Trigger a macro after a new mail is received

I have a macro that prompts you to save an email to a specified folder before you send it, but I can't get the macro to work for receiving emails.
This is what I have for sending emails:
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
If TypeOf Item Is Outlook.MailItem Then
Cancel = Not SaveSentMail(Item)
End If
End Sub
Private Function SaveSentMail(Item As Outlook.MailItem) As Boolean
Dim F As Outlook.MAPIFolder
If Item.DeleteAfterSubmit = False Then
Set F = Application.Session.PickFolder
If Not F Is Nothing Then
Set Item.SaveSentMessageFolder = F
SaveSentMail = True
End If
End If
End Function
Work with Application.Startup Event (Outlook) and Items.ItemAdd Event (Outlook)
Items.ItemAdd Event (Outlook) Occurs when one or more items are added to the specified collection. This event does not run when a large number of items are added to the folder at once. This event is not available in Microsoft Visual Basic Scripting Edition (VBScript).
Application.Startup Event (Outlook) Occurs when Microsoft Outlook is starting, but after all add-in programs have been loaded.
Code Example
Private WithEvents Items As Outlook.Items
Private Sub Application_Startup()
Dim olNs As Outlook.NameSpace
Dim Inbox As Outlook.MAPIFolder
Set olNs = Application.GetNamespace("MAPI")
Set Inbox = olNs.GetDefaultFolder(olFolderInbox)
Set Items = Inbox.Items
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
Dim Folder As Outlook.MAPIFolder
If TypeOf Item Is Outlook.mailitem Then
Set Folder = Application.Session.PickFolder
If Folder Is Nothing Then Exit Sub
Item.Move Folder
End If
End Sub
You can handle the NewMailEx event of the Application class which is fired when a new message arrives in the Inbox and before client rule processing occurs. You can use the Entry ID returned in the EntryIDCollection array to call the NameSpace.GetItemFromID method and process the item. Use this method with caution to minimize the impact on Outlook performance.
Be aware, for users with an Exchange Server account (non-Cached Exchange Mode or Cached Exchange Mode), the event will fire only for messages that arrive at the server after Outlook has started. The event will not fire for messages that are synchronized in Cached Exchange Mode immediately after Outlook starts, nor for messages that are already on the server when Outlook starts in non-Cached Exchange Mode.
Another possible option is to handle the ItemAdd event of the Items class which is fired when one or more items are added to the specified collection. Be aware, this event does not run when a large number of items are added to the folder at once (more than 16 - this is a well-known issue in OOM).
A better solution is to check for new items in the folder using the timer's event. Read more about possible solutions in the following articles:
Outlook NewMail event unleashed: the challenge (NewMail, NewMailEx, ItemAdd)
Outlook NewMail event: solution options
Outlook NewMail event and Extended MAPI: C# example
Outlook NewMail unleashed: writing a working solution (C# example)

Error with Outlook VBA script applied to rule

I have a rule in Outlook which sends a daily email into a particular folder. I then have a VBA script which upon noticing a new unread message in that folder goes in and saves the attachment to a folder on my hard drive and does a few other formatting type things (on the attachment).
I then just linked up the script to the rule in the Outlook rules wizard so it runs as a package.
The problem is as follows: the script is kicked off BEFORE the message is sorted into the appropriate folder. In reality it should run after the message is sorted (otherwise there is nothing for it to act upon). Any ideas on how to rectify?
The code currently begins as follows:
sub saveattachment()
Should it be this instead?
private sub saveattachment()
or
public sub saveattachment()
Would it be better to have the "rule" embedded in the macro instead and then just run it as a private sub anytime the daily email appears in my Inbox?
If you need to assign a VBA macro sub to the Outlook rule, the VBA sub should look like the following one:
Public Sub Test(mail as MailItem)
' your code goes there
End Sub
An instance of the MailItem class is passed as a parameter and stands for the email arrived to the Inbox.
But in case if you need to be sure that your code is triggered when a mail is moved to a particular folder you need to handle the ItemAdd event of the Items class which comes from that folder. Be aware, the event is not fired when more than 16 items are added to the folder simultaneously.
Public WithEvents myOlItems As Outlook.Items
Public Sub Initialize_handler()
Set myOlItems = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderContacts).Items
End Sub
Private Sub myOlItems_ItemAdd(ByVal Item As Object)
Dim myOlMItem As Outlook.MailItem
Dim myOlAtts As Outlook.Attachments
Set myOlMItem = myOlApp.CreateItem(olMailItem)
myOlMItem.Save
Set myOlAtts = myOlMItem.Attachments
' Add new contact to attachments in mail message
myOlAtts.Add Item, olByValue
myOlMItem.To = "Sales Team"
myOlMItem.Subject = "New contact"
myOlMItem.Send
End Sub
Finally, you may find the Getting Started with VBA in Outlook 2010 article helpful.

Outlook reply to multiple emails on demand

Just wondering if this is possible and if it is can someone assist me with?
In this scenario what we do is emails comes into shared folder. We will then have those email sorted.
After the sorting we will start putting emails into an approved folder. What I will like to do is have a VBA macro in outlook that will be able to generate a custom reply to all the emails in the approved folder.
For example if we place 5 emails in the folder and run a script it should send emails out to those 5 senders.
The email will be something generic such as "You are approved, please logout a "time".
I'd suggest starting from the Getting Started with VBA in Outlook 2010 article in MSDN. It explains the basics of programming VBA macros.
The ItemAdd event is fired when one or more items are added to the Items collection (i.e. folder). Be aware, the event is not fired when a large number of items are added to the folder at once.
So, you can handle the ItemAdd event of the approved folder to create and send a reply. The Reply method of Outlook items creates a reply, pre-addressed to the original sender, from the original message. The Send method sends the e-mail message. For example:
Public WithEvents myOlItems As Outlook.Items
Public Sub Initialize_handler()
Set myOlItems = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderContacts).Items
End Sub
Private Sub myOlItems_ItemAdd(ByVal Item As Object)
Dim myOlMItem As Outlook.MailItem
Dim myOlAtts As Outlook.Attachments
Set myOlMItem = myOlApp.CreateItem(olMailItem)
myOlMItem.Save
Set myOlAtts = myOlMItem.Attachments
' Add new contact to attachments in mail message
myOlAtts.Add Item, olByValue
myOlMItem.To = "Sales Team"
myOlMItem.Subject = "New contact"
myOlMItem.Send
End Sub
Outlook reply to multiple emails on demand
Paste the following code in "ThisOutlookSession"
Outlook will automatically send a reply when you move Emails to "approved" folder
Option Explicit
'// items in the target folder to events
Dim WithEvents TargetFolderItems As Items
Private Sub Application_Startup()
Dim olNamespace As Outlook.NameSpace
Set olNamespace = Application.GetNamespace("MAPI")
Set TargetFolderItems = olNamespace.GetDefaultFolder(olFolderInbox) _
'// Set your folder here
.Folders.Item("approved").Items
End Sub
'// ItemAdd event code
Sub TargetFolderItems_ItemAdd(ByVal Item As Object)
Dim olReply As MailItem
Set olReply = Item.Reply
olReply.HTMLBody = "You are approved " & vbCrLf & olReply.HTMLBody
olReply.Send
Set TargetFolderItems = Nothing
Set olReply = Nothing
End Sub