Warn before sending emails to external domains in Outlook - vba

How can you get Outlook to warn you if you are about to send and email to an external domain?
Sending large amounts of emails everyday it is always possible to incorrectly send one to the wrong person. This is especially a problem when they are clients or people outside of your company.
Using Alt + Enter to quickly send emails after typing them for me is often the cause as I do not check the recipients thoroughly.
I have found numerous implementations which were not great so I thought I would share mine below...

Thanks ojhhawkins for the code above - really useful. I've done a simple iteration to include a list of the external email addresses in the MsgBox text.
Word of caution - I've noticed that the warning doesn't appear when you use the Send As Email Attachment in other programmes, eg Excel, Adobe Reader etc. As niton pointed out:
Re:Send As Email Attachment in other programmes. Described in notes here outlookcode.com/d/code/setsavefolder.htm "... does not work on messages created with File | Send commands in Office programs or similar commands in Windows Explorer or other programs. Those commands invoke Simple MAPI, which bypasses Outlook functionality."
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim recips As Outlook.Recipients
Dim recip As Outlook.Recipient
Dim pa As Outlook.PropertyAccessor
Dim prompt As String
Dim strMsg As String
Const PR_SMTP_ADDRESS As String = "http://schemas.microsoft.com/mapi/proptag/0x39FE001E"
Set recips = Item.Recipients
For Each recip In recips
Set pa = recip.PropertyAccessor
If InStr(LCase(pa.GetProperty(PR_SMTP_ADDRESS)), "#example.com") = 0 Then
strMsg = strMsg & " " & pa.GetProperty(PR_SMTP_ADDRESS) & vbNewLine
End If
Next
If strMsg <> "" Then
prompt = "This email will be sent outside of example.com to:" & vbNewLine & strMsg & "Do you want to proceed?"
If MsgBox(prompt, vbYesNo + vbExclamation + vbMsgBoxSetForeground, "Check Address") = vbNo Then
Cancel = True
End If
End If
End Sub
To actually add this code to your Outlook application:
If you can't see the Developer tab in the ribbon bar, go to File/Options, choose Customise Ribbon on the left, and tick Developer on the right.
From the Developer tab choose Visual Basic.
Expand Project1, Microsoft Outlook Objects, and double-click ThisOutlookSession (top left).
Paste the code above into the module.
Replace the "example.com" in the copied code to your domain.
Close the VBA editor and save changes to the module.
On the Developer tab click Macro Security, and change the level to Notifications for all macros or lower.
Restart Outlook. (The code above will not initialise otherwise.)

Add the below code to the Application_ItemSend event in Outlook & change the domain to your own
Change the Macro Security to either (Notifcations for all macros or Enable all macros)
This will provide you with a warning before sending if 1 or more of your TO,CC or BCC address is not in your domain (eg below #mycompany.com.au)
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim recips As Outlook.Recipients
Dim recip As Outlook.Recipient
Dim pa As Outlook.PropertyAccessor
Const PR_SMTP_ADDRESS As String = "http://schemas.microsoft.com/mapi/proptag/0x39FE001E"
Set recips = Item.Recipients
For Each recip In recips
Set pa = recip.PropertyAccessor
If InStr(LCase(pa.GetProperty(PR_SMTP_ADDRESS)), "#mycompany.com.au") = 0 Then
If MsgBox("Send mail to external domain?", vbYesNo + vbQuestion + vbMsgBoxSetForeground, "Check Address") = vbNo Then
Cancel = True
Exit Sub
Else
Exit Sub
End If
End If
Next
End Sub

I found two add-ins for Outlook that does the same if you don't want to use VBA,
www.safesendsoftware.com and
www.sperrysoftware.com.

This short routine can be saved into the Project1->Microsoft Outlook Objects->ThisOutlookSession window in Visual Basic for Applications (under the Outlook Developer tab in the Ribbon - you have to add it with File->Options->Customize Ribbon) and will work out of the box
https://github.com/guyrleech/Microsoft/blob/master/Check%20Outlook%20recipient%20domains.txt

Related

How to Send an Email with a PDF attached with Outlook using MS Access VBA?

I am working with an Access application within Access 2016. The application outputs to a PDF file via the DoCmd.OutputTo method.
I want to either send this PDF attached to an email I build in code, or open a new Outlook email with the file attached.
When I click the button in the form which triggers the code that includes my sub(s) (which are located in separate modules), the email window is never displayed nor is an email sent (depending on the use of .Display vs .Send). I also do not receive any errors.
I think it may also be worth noting that the Call to the sub inside of a module that creates the PDF works as expected.
I am running Access 2016 and Outlook 2016 installed as part of Office 2016 Pro Plus on a Windows 7 64-bit machine. The Office suite is 32-bit.
The Module & Sub
(Email Address Redacted)
Dim objEmail As Outlook.MailItem
Dim objApp As Outlook.Application
Set objApp = CreateObject("Outlook.Application")
Set objEmail = oApp.CreateItem(olMailItem)
With objEmail
.Recipients.Add "email#domain.com"
.Subject = "Invoice"
.Body = "See Attached"
.Attachments.Add DestFile
.Display
End With
The Sub Call
MsgBox "Now saving the Invoice as a PDF"
strInvoiceNbr = Int(InvoiceNbr)
strWhere = "[InvoiceNbr]=" & Me!InvoiceNbr
strDocName = "Invoice Print One"
ScrFile = "Invoice Print One"
DestFile = "Inv" + strInvoiceNbr + " - " + Me.GetLastname + " - " + GetLocation
MsgBox DestFile, vbOKOnly
DoCmd.OpenForm strDocName, , , strWhere
Call ExportToPDF(SrcFile, DestFile, "INV")
Call EmailInvoice(DestFile)
Based on the fact that the PDF is being output within a sub in a Module file, should I be creating the email (or calling the sub) within the sub that creates the PDF?
NOTE: I have looked over this accepted answer here on Stack Overflow, as well as many others. My question differs due to the fact that I am asking why the message is not being displayed or sent, not how to build and send a message as the others are.
EDIT:
Outlook does not open and nothing occurs if Outlook is already open.
Final Note:
To add to the accepted answer, in the VBA editor for Access, you will likely have to go to Tools > References and enable Microsoft Outlook 16.0 Object Library or similar based on your version of Office/Outlook.
To pass full path try using Function EmailInvoice
Example
Option Explicit
#Const LateBind = True
Const olFolderInbox As Long = 6
Public Sub ExportToPDF( _
ByVal strSrcFileName As String, _
ByVal strNewFileName As String, _
ByVal strReportType As String _
)
Dim PathFile As String
Dim strEstFolder As String
strEstFolder = "c:\OneDrive\Estimates\"
Dim strInvFolder As String
strInvFolder = "c:\OneDrive\Invoices\"
' Export to Estimates or Invoices Folder based on passed parameter
If strReportType = "EST" Then
DoCmd.OutputTo acOutputForm, strSrcFileName, acFormatPDF, _
strEstFolder & strNewFileName & ".pdf", False, ""
PathFile = strEstFolder & strNewFileName & ".pdf"
ElseIf strReportType = "INV" Then
DoCmd.OutputTo acOutputForm, strSrcFileName, acFormatPDF, _
strInvFolder & strNewFileName & ".pdf", False, ""
PathFile = strEstFolder & strNewFileName & ".pdf"
End If
EmailInvoice PathFile ' call function
End Sub
Public Function EmailInvoice(FldrFilePath As String)
Dim objApp As Object
Set objApp = CreateObject("Outlook.Application")
Dim objNS As Object
Set objNS = olApp.GetNamespace("MAPI")
Dim olFolder As Object
Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
'Open inbox to prevent errors with security prompts
olFolder.Display
Dim objEmail As Outlook.MailItem
Set objEmail = oApp.CreateItem(olMailItem)
With objEmail
.Recipients.Add "email#domain.com"
.Subject = "Invoice"
.Body = "See Attached"
.Attachments.Add FldrFilePath
.Display
End With
End Function
Your issue is with probably Outlook security. Normally Outlook would show a popup that says that a 3rd party application is attempting to send email through it. Would you like to allow it or not. However since you are doing this programmatically that popup never appears. There used to be a way to bypass this.
Test your program while the user is logged on and has Outlook open. See if there will be any difference in behavior. If that popup does come up, google the exact message and you will probably find a way to bypass it.
Any reason why you not using sendOject?
The advantage of sendobject, is that you not restriced to Outlook, and any email client should work.
So, this code can be used:
Dim strTo As String
Dim strMessage As String
Dim strSubject As String
strTo = "abc#abc.com;def#def.com"
strSubject = "Your invoice"
strMessage = "Please find the invoice attached"
DoCmd.SendObject acSendReport, "rptInvoice", acFormatPDF, _
strTo, , , strSubject, strMessage
Note that if you need to filter the report, then open it first before you run send object. And of course you close the report after (only required if you had to filter, and open the report before - if no filter is to be supplied, then above code will suffice without having to open the report first).
There is no need to separate write out the pdf file, and no need to write code to attach the resulting pdf. The above does everything in one step, and is effectively one line of code.

Trying to create a button in outlook 2010 that replys to highlighted email/open email w/ static text and cc's an email address

Everything seems to work except adding the email address to the cc.
The account I am testing with may be hidden from the GAL.
Also is there a way to add the User's display name to the body text i.e. Great Job (dynamic name i.e. Ted i.e. email sending i am replying to)! I loved your work . . .
Using windows 7 enterprise w/ outlook 2010 professional Plus 32bit and exchange 2010.
Thanks! Code below
Sub GoodJob()
Dim m As MailItem 'object/mail item iterator
Dim recip As Recipient 'object to represent recipient(s)
Dim reply As MailItem 'object which will represent the reply email
'Loop over each SELECTED item:
For Each m In Application.ActiveExplorer.Selection
If m.Class = olMail Then
Set reply = m.reply
'Adds a "direct replies to" address:
'Set recip = reply.ReplyRecipients.Add("g#g.com")
Set recip = reply.ReplyRecipients.Add("someperson#a.net")
recip.Type = olCC
'adds Subject "Great Job! I loved your work on this Project" to email
reply.Subject = "Great Job ! I loved your work on this Project"
'Adds Body of text to email
reply.Body = "Your awesomeness has been shared with Driver X" & vbLf & m.Body
reply.Save 'saves a draft copy to your SENT folder
reply.Send
End If
Next
End Sub
Not ReplyRecipients in this case just Recipients.
Set recip = reply.Recipients.Add("someperson#a.net")

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.

How to hide BCC field in SENT email Outlook 2010 VBA

I have a macro coded to a rule that autoforwards all incoming and sent emails to a private email address in the BCC field (any auto BCC rule is disabled at the server level.) With the help of the board here, the macro works flawlessly, and for all intents and purposes is invisible.
However, if you open the SENT message in the SENT FOLDER, the BCC field is visible to all for the world to see. I have learned this is a "feature" in Outlook, apparently since 2003.
Is there a way to suppress the visibility of the BCC field when viewing the SENT email?
Or is there a way one can set the display options of an individual folder NOT to display a BCC - EVER?
Thank you for any assistance.
My code:
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim objRecip As Recipient
Dim strMsg As String
Dim res As Integer
Dim strBcc As String
Dim answer
Dim oAtt
Dim strProc1 As String
On Error GoTo Application_ItemSend_Error
strBcc = "myprivateemail#gmail.com"
Set objRecip = Item.Recipients.Add(strBcc)
objRecip.Type = olBCC
If Not objRecip.Resolve Then
strMsg = "Could not resolve the Bcc recipient. " & _
"Do you want still to send the message?"
res = MsgBox(strMsg, vbYesNo + vbDefaultButton1, _
"Could Not Resolve Bcc Recipient")
If res = vbNo Then
Cancel = True
End If
End If
Set objRecip = Nothing
On Error GoTo 0
Exit Sub
Application_ItemSend_Error:
MsgBox "Error " & Err.Number & " (" & Err.Description & ") " & "Error on
Line " & Erl & " in procedure Application_ItemSend of VBA Document
ThisOutlookSession"
End Sub
If you want to remove BCC recipients in the Sent Items folder, listen for the Items.ItemAdd event on the Sent Items folder, loop through all recipients in the MailItem.Recipients collection and delete recipients with Recipient.Type = olBCC.
"the BCC field is visible to all for the world to see"
Well, if anyone in the world can view your own sent folder, then this is the case. Otherwise the BCC field is not part of the email, recipients do not receive it. The goal of the feature is to have the ability to recall your own BCC messages, so you do not forget that you have sent them.
Try the following...
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim olRec As Outlook.Recipient
Dim Address$
Address = "Om3r#blala.com"
Set olRec = Item.Recipients.Add(Address)
olRec.Type = olBCC
olRec.Resolve
End Sub