I am trying to send outlook mail using VBA . Every time I run my macro a pop-up comes to me of TITUS stating as select data risk classification. My question is if there any way I can bypass it or select it automatically and send an email.
I have the attempted code snippets to achieve it from multiple sources from internet below.
Sub test()
Dim AOMSOutlook As Object
Dim AOMailMsg As Object
Set AOMSOutlook = CreateObject("Outlook.Application")
Dim objUserProperty As Object
Set AOMailMsg = AOMSOutlook.CreateItem(0)
Set objUserProperty = AOMailMsg.UserProperties.Add("TITUSAutomatedClassification", 1)
objUserProperty.Value = "TLPropertyRoot=ABCDE;Classification=Internal;Registered to:My Companies;"
With AOMailMsg
.To = "v-fexue#outlook.com"
.Subject = "New Report"
.HTMLBody = "Hi"
.Save
.Send
End With
Set AOMailMsg = Nothing
Set objUserProperty = Nothing
Set AOMSOutlook = Nothing
Set lOMailMsg = Nothing
Set objUserProperty = Nothing
Set lOMSOutlook = Nothing
End Sub
Also please clear if objUserProperty.Value = "TLPropertyRoot=ABCDE;Classification=Internal;Registered to:My Companies; Registered to: (has to be actual company name)
Thanks in advance.
You may contact Titus developers for the actual format of the string that needs to be set to avoid any popups from their add-in in Outlook. Also you may check out the sent items for properties set by the add-in, use any low-level property explorer tool such as MFCMAPI or OutlookSpy for that.
Related
I added a UserForm into my file so comments can be added to a cell (that way I can update the data on other cells when a comment is added and someone is mentioned).
So far I can get the comment entered with no issues. But I can´t find a way to #mention a user so the notification is sent. Does anyone know if this is manageable with VBA?
Range("A1").AddCommentThreaded ("Comment text")
Answer
By reading the documentation the method is not likely implemented in VBA and seems only a front end to Excel, but not visible to VBA itself. The only property that I found was "resolved" (which is not mentioned in the documentation of the object itself), but there is not a way to "resolve" it per say.
VBA does not resolve the user (even if it's correctly written) and most likely there is no native way to do so.
Workaroud
Your only solution would be to implement it by yourself: according to your question, since you are using an UserForm I would append something like this
Add the reference for outlook (you may use late binding, but I rather to add the references as it is better IMHO)
In a module, add the following:
Function Return_TxtFoundContact() As String
Dim ObjNamesDialog As Outlook.SelectNamesDialog
Set ObjNamesDialog = Outlook.Session.GetSelectNamesDialog
Dim ObjAddressEntry As Outlook.AddressEntry
With ObjNamesDialog ' 1. With ObjNamesDialog
.Caption = "Select contact to mention & notify": .ToLabel = "Mention:"
.NumberOfRecipientSelectors = olShowTo: .AllowMultipleSelection = False 'although with this setting it lets user to select more than one recipient
If .Display Then ' 1. If .Display
TxtEntryID = .Recipients(1).EntryID: Set ObjAddressEntry = Outlook.Application.Session.GetAddressEntryFromID(TxtEntryID)
Return_TxtFoundContact = ObjAddressEntry.GetExchangeUser.PrimarySmtpAddress
End If ' 1. If .Display
End With ' 1. With ObjNamesDialog
Set ObjAddressEntry = Nothing: Set ObjNamesDialog = Nothing
End Function
Sub Test()
Call Exec_SendNotificationMentionMail("sample#domain.com", Range("E4"))
End Sub
Sub Exec_SendNotificationMentionMail(TxtEmailToSendTo As String, RangeCommentIs As Range)
Dim AppOutlook As Outlook.Application
Set AppOutlook = New Outlook.Application
Dim ObjMailItem As Outlook.MailItem: Set ObjMailItem = AppOutlook.CreateItem(olMailItem)
With ObjMailItem
ObjMailItem.To = TxtEmailToSendTo
'since you may have many users under outlook, I rather to get the application username, however you may go to https://learn.microsoft.com/en-us/office/vba/api/outlook.namespace.currentuser
'to see how to get the username by outlook or use Environ("Username"), varies per needs/company to get the desired outcome
ObjMailItem.Subject = Application.UserName & " mentioned you in '" & ThisWorkbook.Name & "'"
'If you wish, format it as microsoft would do, just research on how to give format to the htmlbody on outlook, for simplicity I just add the basic
ObjMailItem.HTMLBody = Application.UserName & " mentioned you at: " & RangeCommentIs.Address(False, False) & Chr(10) & RangeCommentIs.CommentThreaded.Text
'for debug purposes, display it, once you have verified it works as you would like, comment the line
.Display
'Once you have verified it works as intended, uncomment this
'.Send
End With
'Once you have verified it works as intended, uncomment this
'Set ObjMailItem = Nothing: Set AppOutlook = Nothing
End Sub
In your userform, add a textbox where, upon double clicking, user agenda (per code above) would show up to select from the directory the person being mentioned
Private Sub TextBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Dim TxtFoundContact As String
TxtFoundContact = Return_TxtFoundContact
TextBox1 = TxtFoundContact
End Sub
Finally, on your userform implementation when they hit "OK" or when your userform appends the comment to a mail and send it using the routine.
OT: This method may be more useful than the actual one, you may select users that the workbook has not been shared with, if they get mentioned, but they do not have access yet, they can request it (I think the communication process will be faster with this). I am not quite sure if the original implementation allows it, but if needed, multiple people can be notified under the same mail too, you just need to adjust the code above to do so.
I’m currently working on an access Vba program in order to automatically write mails to people. However we chose to still press ‘Send’ in Outlook manually (in case there are possible issues, so we can control the mail beforehand).
Is there a way to have a link in the other direction, as in, when pressing the Send button in Outlook, getting the email address of the person back in excel? (The goal would be to make a ‘history’ sheet in order to keep track of which mails were actually sent and to whom)
Thank you!
Yes. A simple case is shown below. This is bare bones demonstrating the actions you requested.
Public variable, addressSent, holds the To address. A boolean test on mail sent (by #Rory) tests for the mail item having been sent and calls a function, by #Dwipayan Das, that opens a specified Excel file, and writes the addressSent to cell A1 in sheet1.
You can tinker with this to fit your purposes. E.g. Adapt the function to accept a file name as parameter.....
Taking a note from #ashleedawg's book: remember to include a xlApp.Quit line so Excel is not left hanging.
I believe your question wanted to go from Outlook to Excel so this is the application that you will have created that needs closing.
So in Outlook goes the following code:
Put this in a standard module:
Option Explicit
Public addressSent As String
Dim itmevt As New CMailItemEvents
Public Sub CreateNewMessage()
Dim objMsg As MailItem
Set objMsg = Application.CreateItem(olMailItem)
Set itmevt.itm = objMsg
With objMsg
.Display
.To = "somebody#mail.com"
.Subject = "Blah"
addressSent = .To
.Send
End With
End Sub
Public Function openExcel() As Boolean 'Adapted from #Dwipayan Das
Dim xlApp As Object
Dim sourceWB As Object
Dim sourceWS As Object
Set xlApp = CreateObject("Excel.Application")
With xlApp
.Visible = True
.EnableEvents = False
End With
Dim strFile As String
strFile = "C:\Users\User\Desktop\Delete.xlsb" 'Put your file path.
Set sourceWB = xlApp.Workbooks.Open(strFile, , False, , , , , , , True)
sourceWB.Activate
sourceWB.Worksheets(1).Range("A1") = addressSent
End Function
Then in a class module called CMailItemEvents, code from #Rory, put the following:
Option Explicit
Public WithEvents itm As Outlook.MailItem
Private Sub itm_Close(Cancel As Boolean)
Dim blnSent As Boolean
On Error Resume Next
blnSent = itm.Sent
If Err.Number = 0 Then
Debug.Print "not sent"
Else
openExcel
End If
End Sub
References:
Check to see if an Outlook Email was sent from Excel VBA
How can I use Outlook to send email to multiple recipients in Excel VBA
How to open an excel file in Outlook vba code
Create a new Outlook message using VBA
Run code after item sent
Just a quick 'n dirty function that will run in Excel/Access/Word and returns the email address from the most recent item in the Sent Items folder (no error handling, etc):
Function LastSentEmailAddress() As String
'Requires reference: "Microsoft Outlook xx.x Object Library"
Dim olApp As Outlook.Application, olMail As Object
Set olApp = New Outlook.Application 'create Outlook object
Set olMail = olApp.GetNamespace("MAPI").GetDefaultFolder(olFolderSentMail).Items.GetLast
LastSentEmailAddress = olMail.Recipients(1).PropertyAccessor.GetProperty( _
"http://schemas.microsoft.com/mapi/proptag/0x39FE001E") 'get email addy
olApp.Quit 'close Outlook
End Function
A Note about working with Outlook objects from Excel:
When working with applications such as Excel it's important to make sure the application object is properly .Quit / .Close'd when finished with them, (and to Set all objects to Nothing), otherwise there's a risk of inadvertently having multiple instances running, which can lead to memory leaks, which leads to crashes and potential data loss.
To check if there is an existing instance of Outlook, use this function:
Function IsOutlookOpen()
'returns TRUE if Outlook is running
Dim olApp As Outlook.Application
On Error Resume Next
Set olApp = GetObject(, "Outlook.Application")
On Error GoTo 0
If olApp Is Nothing Then
IsOutlookOpen= False
Else
IsOutlookOpen= True
End If
End Function
(Source: Rob de Bruin)
More Information:
MSDN : Items.GetLast Method (Outlook)
MSDN : Items Object (Outlook)
MSDN : Obtain the E-mail Address of a Recipient
Office.com : How to disable warnings about programmatic access to Outlook
MSDN : Chapter 17: Working with Item Bodies (Book Excerpt)
MSDN : Check or Add an Object Library Reference
Stack Overflow : VBA to search an Outlook 2010 mail in Sent Items from Excel
I wrote a program in Excel 2010 to sift through emails in a selected Outlook 2010 folder, and pull in information from the email (html) body.
I updated to Office 2016. Since then, I get an error when using certain properties of the MailItem object. I can pull the subject of the email into Excel, but certain properties cause a "method 'body' of object'_mailItem" failed error (including the .Body and .To properties).
Below is a simplified version of the code:
Sub GatherInfo()
Dim ObjOutlook As Object
Dim MyNamespace As Object
Dim FormFolder As Object
Set ObjOutlook = GetObject(, "Outlook Application")
Set MyNamespace = ObjOutlook.GetNamespace("MAPI")
Set FormFolder = MyNamespace.PickFolder
For i = 1 To FormFolder.Items.Count
Range("A2").Select
ActiveCell.Value = FormFolder.Items(i).Subject
ActiveCell.Offset(0, 1).Value = FormFolder.Items(i).To
End Sub
This results in:
Run-time error '-2147467259(80004005)':
Method 'To' of object'_MailItem' failed
I've done some research, and wondering if Outlook 2016 security settings could be to blame.
This is a corporate email account, running on an exchange server. Do you think that could be preventing me from accessing the body/sender of the email?
It's strange that the subject property of the email works, but not the body/to properties.
Things I've ruled out:
1) I've sent both plain text and html based emails with the same result.
2) I've tried binding the Outlook objects early (Dim ObjOutlook as Outlook.Application, etc.)
I ensured there were only mail items and no calendar items, etc.
It'll trip out the first time it hits the item.To assignment. If I insert a line to resume next then it'll go through all the emails, but will only record the subject and not the .To property.
Avoid using multiple dot notation and check if you really have a MailItem object (you can also have ReportItem or MeetingItem):
set items = FormFolder.Items
For i = 1 To items.Count
set item = items.Item(i)
if item.Class = 43 Then
Range("A2").Select
ActiveCell.Value = item.Subject
ActiveCell.Offset(0, 1).Value = item.To
End If
set item = Nothing
next
set items = Nothing
I want to create a meeting invite only to book a room in outlook through Excel.
this is the code I am using,
Private Sub CommandButton2_Click()
Set myOutlook = CreateObject("Outlook.Application")
Set myApt = myOutlook.CreateItem(1)
myApt.Subject = "Training"
myApt.Start = Now
myApt.RequiredAttendees = "B 101-Training Room-24 <B101-TrainingRoom-24.IOC#cummins.com>"
myApt.End = Now + 30
myApt.MeetingStatus = olMeeting
myApt.send
MsgBox ("Meeting Invite Sent")
Set myOutlook = Nothing
Set myApt = Nothing
End Sub
this code doesnot create any meeting invite, but doesnot give error as well.
Can please tell what could be the missing thing?
Thanks.
I think you'd better use recipients, trying this
myApt.Recipients.Add("B 101-Training Room-24 <B101-TrainingRoom-24.IOC#cummins.com>")
The RequiredAttendees property only contains the display names for the required attendees. The attendee list should be set by using the Recipients collection.
Resources are usually added as BCC recipients:
set recip = myApt.RequiredAttendees("B 101-Training Room-24 <B101-TrainingRoom-24.IOC#cummins.com>")
recip.Type = 3 'olBCC
recip.Resolve
Do you see the meeting request in the Sent Items folder?
the code given adds all the fields except attendees. I want to have 'Invite attendees' option coded.
Set recip = myApt.RequiredAttendees("B 101-Training Room-24 <B101-TrainingRoom-24.IOC#cummins.com>")
is there any other way to add the invitees? FYI, I am using Outlook 2013.
I'm trying to send an Outlook email from Excel 2010 using VBA.
Most answers on Stack Overflow don't seem to have a method of using VBA to avoid the Outlook security warning, nor for Outlook/Excel 2010.
Do any free methods exist? The Redemption method won't be a viable option, unless it is easy to install on 10 machines in a large company.
How I send emails:
Dim emailAddr As String
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = "xxxx#xxxx.edu"
.Subject = "Demande"
.HtmlBody = CombinedValueHtml
.Send
End With
Set OutMail = Nothing
Set OutApp = Nothing
Exit Sub
This is a partial answer. I have made it a Community Wiki answer in the expectation that someone else can explain the final part which I cannot get to work.
This web page, http://msdn.microsoft.com/en-us/library/office/aa155754(v=office.10).aspx , explains the first three parts of the process. It was written in 1999 so cannot be followed exactly because it refers to old versions of Windows and Office.
The first step is to add Digital Signature for VBA Projects to your Office installation although I found it under Shared Tools rather than Office Tools. Don't make the mistake of just adding Digital Signature for VBA Projects to Outlook because, as I discovered, that means you uninstall Word, Excel, etc.
The second step is to run Selfcert.exe to create a digital certificate in your own name.
The third step is to open Outlook's VBA editor, select Tools then Digital Certificate then Choose to sign the project with your certificate.
With these steps you can suppress the warning that Outlook contains macros but this does not suppress that warning that a macro is accessing emails. To suppress that warning, you need a fourth step which is to place your certificate within the Trusted Root Certificate Authorities Store. This web page http://technet.microsoft.com/en-us/library/cc962065.aspx explains about the Certification Authority Trust Model but I cannot successfully use Microsoft Management Console to achieve the fourth step.
Instead .send use the following:
.Display 'displays outlook email
Application.SendKeys "%s" 'presses send as a send key
note: be careful when using display keys, if you move the mouse and click while the program is running it can change whats going on. also outlook will display on ur screen and send.. if you working on something else's and this bothers you, yea.. not the best idea
The Redemption method won't be a viable option, unless it is easy to
install on 10 machines inside of a large company.
You can use RedemptionLoader (I am its author) - it loads the dll directly and does no require the dll to be installed using the registry.
It is either Extended MAPI in C++ or Delphi, Redemption (I am its author - wraps Extended MAPI and can be used form any language) or a utility like ClickYes.
If you don't send the message immediately but just display it and let the user do modifications (if any) and let them press the send button theirselves, this would work:
i.e. use
.Display
instead of
.Send
I explained how you can use vba to send emails in this answer You will find a macro that I use extensively in my daily work.
Following recomendations from #Floern, here is the explanation:
In order to insert images (signature as images) you could use the following code:
Step 1. Copy this code an paste in class module and name that class module like "MailOptions"
Private Message As CDO.Message
Private Attachment, Expression, Matches, FilenameMatch, i
Public Sub PrepareMessageWithEmbeddedImages(ByVal FromAddress, ByVal ToAddress, ByVal Subject, ByVal HtmlContent)
Set Expression = CreateObject("VBScript.RegExp")
Expression.Pattern = "\<EMBEDDEDIMAGE\:(.+?)\>"
Expression.IgnoreCase = True
Expression.Global = False 'one match at a time
Set Message = New CDO.Message
Message.From = FromAddress
Message.To = ToAddress
Message.Subject = Subject
'Find matches in email body, incrementally increasing the auto-assigned attachment identifiers
i = 1
While Expression.Test(HtmlContent)
FilenameMatch = Expression.Execute(HtmlContent).Item(0).SubMatches(0)
Set Attachment = Message.AddAttachment(FilenameMatch)
Attachment.Fields.Item("urn:schemas:mailheader:Content-ID") = "<attachedimage" & i & ">" ' set an ID we can refer to in HTML
Attachment.Fields.Item("urn:schemas:mailheader:Content-Disposition") = "inline" ' "hide" the attachment
Attachment.Fields.Update
HtmlContent = Expression.Replace(HtmlContent, "cid:attachedimage" & i) ' update the HTML to refer to the actual attachment
i = i + 1
Wend
Message.HTMLBody = HtmlContent
End Sub
Public Sub SendMessageBySMTP(ByVal SmtpServer, ByVal SmtpUsername, ByVal SmtpPassword, ByVal UseSSL)
Dim Configuration
Set Configuration = CreateObject("CDO.Configuration")
Configuration.Load -1 ' CDO Source Defaults
Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = SmtpServer
'Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = SmtpPort
Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout") = 30
If SmtpUsername <> "" Then
Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusername") = SmtpUsername
Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") = SmtpPassword
End If
Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = UseSSL
Configuration.Fields.Update
Set Message.Configuration = Configuration
Message.Send
End Sub
Step 2. In an standar module you will elaborate your .html content and instantiate a object from the class:
public sub send_mail()
Dim signature As String
dim mail_sender as new MailOptions 'here you are instantiating an object from the class module created previously
dim content as string
signature = "C:\Users\your_user\Documents\your_signature.png"
content = "<font face=""verdana"" color=""black"">This is some text!</font>"
content = content & "<img src=""<EMBEDDEDIMAGE:" & signature & " >"" />"
mail_sender.PrepareMessageWithEmbeddedImages _
FromAddress:="chrism_mail#blablabla.com", _
ToAddress:="addressee_mail#blablabla.com", _
Subject:="your_subject", _
HtmlContent:=content
'your_Smtp_Server, for example: RelayServer.Contoso.com
correos.SendMessageBySMTP "your_Smtp_Server", "your_network_user_account", "your_network_user_account_password", False
end sub