send outlook mail from excel vba - vba

I have the following code that sends outlook mail. But this will not work when outlook is closed.
Sub DraftMail(emailAddr, strBody, strSub)
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = GetObject(, "Outlook.Application")
If OutApp Is Nothing Then
Set OutApp = CreateObject("Outlook.Application")
End If
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = ""
.CC = ""
.BCC = emailAddr
.Subject = strSub
.HTMLBody = strBody
.Send 'or use .Display
.ReadReceiptRequested = True
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Can anybody help me how to make it work even when the outlook is closed?

Try this code :
(Not tested)
Sub SendMail()
Dim iMsg As Object
Dim iConf As Object
Dim Flds As Variant
Set iMsg = CreateObject("CDO.Message")
Set iConf = CreateObject("CDO.Configuration")
iConf.Load -1
Set Flds = iConf.Fields
With Flds
.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "<server>"
.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
.Update
End With
With iMsg
Set .Configuration = iConf
.To = "test#gmail.com"
.From = "test#gmail.com"
.Subject = "MIS Reports" & " " & Date & " " & Time
.TextBody = "Link to Currency Data :" & vbNewLine & "<" & myDest & ">"
.Send
End With
Set iMsg = Nothing
Set iConf = Nothing
End Sub

First do you have any error handling in there? For example if you call getObject and it is closed you should get an error?
So the way that most people use is to call get object and if that errors then they know outlook is closed and they create a new instance.
If you want to be very precise the error code number is 429 see for example this code here Link to previous question.
To get you started this should also work
On Error Resume Next
Set OutApp = GetObject(, "Outlook.Application")
If OutApp Is Nothing Then
Set OutApp = CreateObject("Outlook.Application")
End If
Once you have this working then you can remove the "On Error Resume Next" and catch the specific error 429 if you want, and then you know that the error is because Outlook is not running.

The easiest thing to do is construct a mailto:// url and run it through a shell command.
You must URL encode the subject and body for it to show up properly.
example (paste in Run command in Windows):
mailto://user#domain.com?subject=New%20Email&body=This%20is%20the%20message%20body.

Related

Verify via vba to msaccess 2013 that email was sent to Outlook 2013

I am trying to achieve:
the email was sent to Outlook "Sent Items" folder therefore email is
not in the "Outbox" folder.
email did not return due to delivery failure (email will be in the
"Inbox" folder deliver by postmaster#mail.hotmail.com)
The following code is used to send an email from an Access form via Outlook:
Private Sub cmdEmail1_Click()
Dim OutApp As Outlook.Application
Dim OutMail As Outlook.MailItem
Dim strBody As String
Dim strPDF As String
Dim strFolder As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(olMailItem)
strBody = Me.txtSubject
strPDF = Me.txtFile
On Error Resume Next
With OutMail
.To = Me.txtemail
.CC = ""
.BCC = Me.txtBBCemail
.Subject = Me.txtSubject
.Body = Me.txtMessage
.Recipients.ResolveAll
' .SendUsingAccount = OutApp.Session.Accounts.Item(2) '2nd email
.SentOnBehalfOfName = Me.txtFromEmail
.Attachments.Add strPDF 'attachments
.Send
End With
Me.txtSent = "email was sent to Outlook "
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Thanks a lot
Norbert
Both of these will be asynchronous and you will be able to process the notification at a later point, seconds or even minutes later.
I don't think #1 will help you much - it only tells you that the network was not disconnected. Why does it matter? Even if it is down, Outlook will send the message later.
For #2, it all depends on who sent the NDR. If it is Exchange, you will be able to figure out the bad recipient address. Otherwise you might just get a message with no good way to figure out what the problematic recipient was.
EDIT. For Items.ItemAdd, see the following (off the top of my head):
Dim OutApp As Outlook.Application
Dim WithEvents SentItems As Outlook.Items
sub SentItems_ItemAdd(Item As Object)
MsgBox Item.Subject
end sub
Private Sub cmdEmail1_Click()
Dim OutMail As Outlook.MailItem
Dim strBody As String
Dim strPDF As String
Dim strFolder As String
Dim ns As Outlook.Namespacee
if (OutApp Is Nothing) Then
Set OutApp = CreateObject("Outlook.Application")
set ns = OutApp.GetNamespace("MAPI")
ns.Logon
set SentItems = ns.GetDefaultFolder(olFolderSentMail).Items
End If
Set OutMail = OutApp.CreateItem(olMailItem)
strBody = Me.txtSubject
strPDF = Me.txtFile
On Error Resume Next
With OutMail
.To = Me.txtemail
.CC = ""
.BCC = Me.txtBBCemail
.Subject = Me.txtSubject
.Body = Me.txtMessage
.Recipients.ResolveAll
' .SendUsingAccount = OutApp.Session.Accounts.Item(2) '2nd email
.SentOnBehalfOfName = Me.txtFromEmail
.Attachments.Add strPDF 'attachments
.Send
End With
Me.txtSent = "email was sent to Outlook "
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub

How to CC the sender?

I have code to send email. I'm struggling to CC the sender? If I mail I should get the CC, if my colleague mails he should get the CC.
Our usernames aren't firstname.lastname but our email addresses are.
Sub SendPDF()
Dim strPath As String, strFName As String
Dim OutApp As Object, OutMail As Object
Title = Format(Now(), "dd/mm/yyyy") & " - " & ActiveSheet.Name & ""
strPath = Environ$("temp") & "\" 'Or any other path, but include trailing "\"
strFName = ActiveWorkbook.Name
strFName = Format(Now(), "yyyymmdd") & " - " & ActiveSheet.Name & ".pdf"
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
strPath & strFName, Quality:=xlQualityStandard, _
IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=False
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "firstname.surname#email.com"
.CC = ""
.BCC = ""
.Subject = Title
.body = "Please see attached"
.Attachments.Add strPath & strFName
'.Display
.Send
End With
Kill strPath & strFName
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
You can use the CurrentUser property of the Namespace class to get the currently logged-on user as a Recipient object. Then you can get the Address property value which representing the e-mail address of the Recipient.
.CC = nameSpace.CurrentUser.Address;
Also you may find the How To: Fill TO,CC and BCC fields in Outlook programmatically article helpful.
Sub email()
Dim a As Integer
Dim objOutlook As Object
Dim objMail As Object
Dim rngTo As Range
Dim rngCc As Range
Dim rngBcc As Range
Dim rngSubject As Range
Dim rngAttach As Range
Dim rngBody As Range
Set objOutlook = CreateObject("Outlook.Application")
Set objMail = objOutlook.CreateItem(0)
With ActiveSheet
Set rngTo = .Range("B1")
Set rngCc = .Range("B2")
Set rngBcc = .Range("B3")
Set rngSubject = .Range("B4")
Set rngAttach = .Range("B5")
Set rngBody = .Range("B6")
End With
With objMail
.To = rngTo.Value
.Cc = rngCc.Value
.Bcc = rngBcc.Value
.Subject = rngSubject.Value
.Attachments.Add rngAttach.Value
.Body = rngBody.Value
.Display
End With
Set objOutlook = Nothing
Set objMail = Nothing
Set rngTo = Nothing
Set rngCc = Nothing
Set rngBcc = Nothing
Set rngSubject = Nothing
Set rngAttach = Nothing
Set rngBody = Nothing
End Sub
I know this is kind of old, but I ended up here, so someone else might!
I was able to get the sender CC'd using the namespace (at least in an exchange environment). In my case, the CurrentUser. The address returned a string like the following:
/o=ExchangeLabs/ou=Exchange Administrative Group (XXXXXXXXXXXXXXXX)/cn=Recipients/cn=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX-XXXXXXX
This was resolved successfully, and successfully CC'd the sender.
Might also look at Get sender's email address with Excel VBA
Sub TestCC()
Dim OutApp As Outlook.Application
Dim OutMail As Outlook.MailItem
Dim OutNS As Outlook.Namespace
' Get open Outlook, or create a new instance
On Error Resume Next
Set OutApp = GetObject(, "Outlook.Application")
If OutApp Is Nothing Then Set OutApp = CreateObject("Outlook.Application")
On Error GoTo 0
' Get MAPI Namespace
Set OutNS = OutApp.GetNamespace("MAPI")
' Create Mail Item
Set OutMail = OutApp.CreateItem(olMailItem) 'Item type 0
' Build email
On Error Resume Next
With OutMail
.To = "first.last#email.com"
.CC = OutNS.CurrentUser.Address
.BCC = ""
.Subject = "Email Subject Line"
.Body = "Body Text"
' Resolve added recipients
.Recipients.ResolveAll
' Display or Send created email
.Display
'.Send
End With
' Clean up
Set OutMail = Nothing
Set OutNS = Nothing
Set OutApp = Nothing
End Sub

Add signature with images to the Mail

I have a macro for Outlook where I can create a complete mail with an attachment but can not add a signature saved in my C drive (C:\Users\JustinG\AppData\Roaming\Microsoft\Signatures).
Signature types are .rtf and .htm with images.
The following is the code:
Sub Mail_Workbook_1()
Dim OutApp As Object
Dim Outmail As Object
Set OutApp = CreateObject("Outlook.Application")
Set Outmail = OutApp.CreateItem(0)
On Error Resume Next
' Change the mail address and subject in the macro before you run it.
With Outmail
.SentOnBehalfOfName = "justin.gatlin#rediffmail.com"
.To = "abc#xyz.com"
.CC = ""
.BCC = ""
.Subject = "Presentation"
.Body = "Hi Team,"
.Attachments.add ("C:\Users\DurshetwarA\Desktop\Excel Examination_Master_V1.xlsx")
.display
''SendKeys ("%s")
End With
On Error GoTo 0
Set Outmail = Nothing
Set OutApp = Nothing
End Sub
In the .htm file in the signatures directory you can edit the htm file. The pictures are stored as relative path and when you use the code it looses that path so if you use discrete path it will be able to find the pictures. so go into the file and look for any relative paths and make them discrete.
"/Microsoft/Signatures/picturefile.jpg"
change that to include the whole path
"/root/user/blah blah../Microsoft/Signatures/picturefile.jpg"
This solved the missing image problem for me.
Solution described here by Ron de Bruin.
Sub Mail_Outlook_With_Signature_Html_2()
' Don't forget to copy the function GetBoiler in the module.
' Working in Office 2000-2013
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Dim SigString As String
Dim Signature As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "<H3><B>Dear Customer Ron de Bruin</B></H3>" & _
"Please visit this website to download the new version.<br>" & _
"Let me know if you have problems.<br>" & _
"Ron's Excel Page" & _
"<br><br><B>Thank you</B>"
'Change only Mysig.htm to the name of your signature
SigString = Environ("appdata") & _
"\Microsoft\Signatures\Mysig.htm"
If Dir(SigString) <> "" Then
Signature = GetBoiler(SigString)
Else
Signature = ""
End If
On Error Resume Next
With OutMail
.To = ""
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.HTMLBody = strbody & "<br>" & Signature
.Send 'or use .Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Function GetBoiler(ByVal sFile As String) As String
'Dick Kusleika
Dim fso As Object
Dim ts As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(sFile).OpenAsTextStream(1, -2)
GetBoiler = ts.readall
ts.Close
End Function
Instead of .body use .htmlbody and design your message body in HTML. This is the only way of inserting image in your message. There is no specific option to insert signature
Similar to the solution posted by Adavid02, here you may find a more detailed explanation.

Sending multiple e-mail messages VBA

I tried the following code (I changed the real e-mail address), and it does work on the first cell in range, but after the first one, it gives me an error says: "run time error, the item has been moved or deleted", and then, it does not sending the others.... what should I need to fix in code ?
Sub sendMailWithLoop()
Dim missmatchCell As Range
Dim Missmatches_Rng As Range
Dim entityForRepeatedValues_Rng As Range
Dim OutMail As Object
Dim OutApp As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
If Range("D1000").End(xlUp).Value <> "Name" Then
Set Missmatches_Rng = Range(Range("D1000").End(xlUp), Range("D1000").End(xlUp).End(xlUp).Offset(1, 0))
Missmatches_Rng.Select
For Each missmatchCell In Selection
With OutMail
.To = "mymail#servername.com"
.Subject = "Attention !! missmatch found"
.Body = "The missmatch name is: " & missmatchCell.Offset(0, 1) & ", on: " & missmatchCell
.Send
End With
Next
End If
End Sub
thx !!
Move your Set OutMail = OutApp.CreateItem(0) inside the For as:
Sub sendMailWithLoop()
Dim missmatchCell As Range
Dim Missmatches_Rng As Range
Dim entityForRepeatedValues_Rng As Range
Dim OutMail As Object
Dim OutApp As Object
Set OutApp = CreateObject("Outlook.Application")
If Range("D1000").End(xlUp).Value <> "Name" Then
Set Missmatches_Rng = Range(Range("D1000").End(xlUp), Range("D1000").End(xlUp).End(xlUp).Offset(1, 0))
Missmatches_Rng.Select
For Each missmatchCell In Selection
Set OutMail = OutApp.CreateItem(olMailItem)
With OutMail
.To = "mymail#servername.com"
.Subject = "Attention !! missmatch found"
.Body = "The missmatch name is: " & missmatchCell.Offset(0, 1) & ", on: " & missmatchCell
.Send
End With
Next
End If
End Sub

MS Access / Outlook 2010 - how to choose which account to send email from?

I am trying to send emails from a specific account but it always sends from my main no matter how much code I try or what I do. Is there any way to tell it to send it from a particular account? I am writing my code in MS Access, but using Outlook objects.
Sub testEmail()
On Error Resume Next
Set outapp = GetObject(, "Outlook.Application")
If outapp Is Nothing Then
Set outapp = CreateObject("Outlook.Application")
End If
Set oMail = outapp.CreateItem(olMailItem)
With oMail
.To = "randomaddress#randomdomain.com"
.Subject = "test2"
.Send
End With
Set outapp = Nothing
Set oMail = Nothing
End Sub
Updated code:
Option Compare Database
Sub testEmail()
On Error Resume Next
Set oApp = CreateObject("Outlook.Application")
Set oMail = oApp.CreateItem(olMailItem)
Set olAccount = oApp.Account
Set olAccountTemp = oApp.Account
Dim foundAccount As Boolean
Dim strFrom As String
strFrom = "FROMADDY#randomaddress.com"
foundAccount = False
Set olAccounts = oApp.Application.Session.Accounts
For Each olAccountTemp In olAccounts
Debug.Print olAccountTemp.smtpAddress
If (olAccountTemp.smtpAddress = strFrom) Then
Set olAccount = olAccountTemp
foundAccount = True
Exit For
End If
Next
If foundAccount Then
Debug.Print "ACCT FOUND!"
With oMail
.To = "randomaddress#random.com"
.Body = "Message!"
.Subject = "test3"
.sendusingaccount = olAccount
End With
Else
Debug.Print "No acct found"
End If
Set oApp = Nothing
Set oMail = Nothing
Set olAccounts = Nothing
Set olAccount = Nothing
Set olAccountTemp = Nothing
End Sub
Try using
Set oMail.sendusingaccount=olAccount
instead of
oMail.sendusingaccount=olAccount
It worked for me, your code is perfect, just the Set is missing.
It is also much easier when the user can select the email address rather than account number. sendCaller loops through the accounts until it finds this email address. From there on it will call sendFile from where the message will be sent.
Sub sendCaller()
'creates outlook application
'chooses an email address and finds the corresponding account number
Dim OutApp As Object
Dim i As Integer, accNo As Integer
Set OutApp = CreateObject("Outlook.Application")
emailToSendTo = "name#domain.com" 'put required email address
'if smtp address=email we want to send to, acc no we are looking for is identified
For i = 1 To OutApp.Session.Accounts.Count
'Uncomment the Debug.Print command to see all email addresses that belongs to you
'''Debug.Print "Acc name: " & OutApp.Session.Accounts.Item(i) & " Acc number: " & i & " email: " & OutApp.Session.Accounts.Item(i).smtpAddress
If OutApp.Session.Accounts.Item(i).smtpAddress = emailToSendTo Then accNo = i
Next i
sendFile accNo
End Sub
Sub sendFile(accountNo As Integer)
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = "recipient#domain.com"
.Subject = "Test"
.Body = "Body"
Set .SendUsingAccount = OutApp.Session.Accounts.Item(accountNo)
.Send
End With
End Sub