How to send mail when outlook is closed - vba

i have following lines of code. It works fine when outlook is opened but i want it to work even though outlook is closed. I kept the code in command button click event.
Private Sub btnSend_Click()
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = GetObject("", Outlook.Application)
OutApp.Session.Logon
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "adbc#adbc.com"
.CC = ""
.BCC = ""
.Subject = "Test mail from Excel Sheet-OutLook Closed"
.Body = "This is body of the mail"
.Display
.Send
.ReadReceiptRequested = True
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
I tried it with both GetObject and CreateObject methods. If i execute this code after closing outlook it's not showing any error but it's not sending any mail.
The following lines of code sending the mails but they are queuing in the outlook's outbox. when user opens outlook then only they are moving out from outbox.
Private Sub btnSend_Click()
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "adbc#adbc.com"
.CC = ""
.BCC = ""
.Subject = "Test mail from Excel Sheet-OutLook Closed"
.Body = "This is body of the mail"
.Display
.Send
.ReadReceiptRequested = True
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub

You can use shell commands to actually open outlook before sending a mail.Precisely being
Public Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Public Sub OpenOutlook()
Dim ret As Long
On Error GoTo aa
ret = ShellExecute(Application.hwnd, vbNullString, "Outlook", vbNullString, "C:\", SW_SHOWNORMAL)
If ret < 3 Then
MsgBox "Outlook is not found.", vbCritical, "SN's Customised Solutions"
End If
aa:
End Sub
keep this in a separate module and call the module from the code where you are sending the mail.The part i am trying to work on is how to hide this so that activation is still with excel

For Outlook 2013, this is an issue with Outlook settings, not the VBA code.
Open OUTLOOK
Go To FILE -> OPTIONS -> ADVANCED
Scroll to 'Send and Receive' heading and click 'Send/Receive…' button
Under 'Setting for group 'All Accounts' ', ensure that 'Perform an
automatic send/receive when exiting' is CHECKED
This ensures all items in the OUTLOOK 'Outbox' are sent when Outlook closes. This fixed the issue for me. Likely similar for other versions of Outlook.

Related

Paste Table Copied From Website into Body of Outlook Email Using VBA

I have this code that creates an email, fills in the to, cc, subject fields; and I want it to text the table that I manually copied from the Internet. So basically I want it to do a ctrl-v in the body of the email. I have tried the doclipboard.GetText method and a few other methods. This is the most recent try.
Sub SendEmail(ByVal strSubject As String, ByVal strBody As String, ByVal blnDisplay As Boolean, ByVal blnAddPaste As Boolean)
Dim bStarted As Boolean
Dim oOutlookApp As Outlook.Application
Dim oItem As Outlook.MailItem
On Error Resume Next
'Get Outlook if it's running
Set oOutlookApp = GetObject(, "Outlook.Application")
If Err <> 0 Then
'Outlook wasn't running, start it from code
Set oOutlookApp = CreateObject("Outlook.Application")
bStarted = True
End If
'Create a new mailitem
Set oItem = oOutlookApp.CreateItem(olMailItem)
With oItem
'Set the recipient for the new email
.To = "Email Addresses"
'Set the recipient for a copy
'.CC = strCC
'Set the subject
.Subject = "Salesforce " & EmailDateFormat & " " & strSubject
'The content of the document is used as the body for the email
If blnAddPaste Then
.HTMLBody = strBody & "<br><br>" & _
Selection.PasteAndFormat(Word.WdRecoveryType.wdTableOriginalFormatting) ' this is what I need to fix
Else
.HTMLBody = strBody
End If
If blnDisplay Then
.Display
Else
.Send
End If
End With
If bStarted Then
'If we started Outlook from code, then close it
oOutlookApp.Quit
End If
'Clean up
Set oItem = Nothing
Set oOutlookApp = Nothing
End Sub
How do I get a table to paste inside of the outlook email?
I figured it out for anyone else looking for the solution.
Sub SendEmail(ByVal strSubject As String, ByVal strBody As String, ByVal blnDisplay As Boolean, ByVal blnAddPaste As Boolean)
Dim bStarted As Boolean
Dim oOutlookApp As Outlook.Application
Dim oItem As Outlook.MailItem
Dim oWordDoc As Word.Document
Dim oWordRange As Word.Range
Dim VarPosition As Variant
On Error Resume Next
'Get Outlook if it's running
Set oOutlookApp = GetObject(, "Outlook.Application")
If Err <> 0 Then
'Outlook wasn't running, start it from code
Set oOutlookApp = CreateObject("Outlook.Application")
bStarted = True
End If
'Create a new mailitem
Set oItem = oOutlookApp.CreateItem(olMailItem)
With oItem
If blnDisplay Then
.Display
End If
Set oWordDoc = oItem.GetInspector.WordEditor
'Set the recipient for the new email
.To = "Email Addresses"
'Set the recipient for a copy
'.CC = strCC
'Set the subject
.Subject = "Salesforce " & EmailDateFormat & " " & strSubject
'The content of the document is used as the body for the email
If blnAddPaste Then
.Body = strBody '& Selection.PasteAndFormat(Word.WdRecoveryType.wdTableOriginalFormatting)
VarPosition = oWordDoc.Range.End - 1
Set oWordRange = oWordDoc.Range(VarPosition, VarPosition)
oWordRange.Select
oWordRange.PasteAndFormat (Word.WdRecoveryType.wdFormatOriginalFormatting)
'SendKeys ("^v")
Else
.HTMLBody = strBody
End If
If Not blnDisplay Then
.Send
End If
End With
If bStarted Then
'If we started Outlook from code, then close it
oOutlookApp.Quit
End If
'Clean up
Set oItem = Nothing
Set oOutlookApp = Nothing
End Sub

If there is no attachment file is present at path mail should not send

If there is no attachment file is present at path mail should not send.
Is there any possibility that mail should not be send if there is no attachment?
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = " Hello"
On Error Resume Next
With OutMail
.to = "test#gmail.com"
.cc = "test1#gmail.com"
.BCC = ""
.Subject = "TRANSACTING : " & Format(Date, "DD-MMM-YYYY")
.HTMLBody = strbody
'You can add an attachment like this
.Attachments.Add ("E:\Auto Reports\test.xlsb")
.send 'or use .Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
First of all using On Error Resume Next in the way you did just mute any errors. But the errors still occur they just don't show. Using On Error Resume Next is a very bad practice and you should avoid that unless you really know why you need to do it.
Instead you should always implement a proper error handling like below.
Now the error is shown if adding an attachment to the email fails and the email is not sent.
Option Explicit
Public Sub SendMyEMail()
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = " Hello"
On Error GoTo MAIL_ERROR 'jump to the error handler if an error occurs
With OutMail
.to = "test#gmail.com"
.cc = "test1#gmail.com"
.BCC = ""
.Subject = "TRANSACTING : " & Format(Date, "DD-MMM-YYYY")
.HTMLBody = strbody
'You can add an attachment like this
.Attachments.Add ("C:\Auto Reports\test.xlsb")
.send 'or use .Display
End With
On Error GoTo 0 'stop error handling here (no jumps to the error handler anymore.
'The following 2 lines can be omitted because it is done automatically on exit sub
'So these are completely unnecessary.
'Set OutMail = Nothing
'Set OutApp = Nothing
Exit Sub 'we need this to not to run into error handler if everything was ok
MAIL_ERROR: 'Show error message
MsgBox "An error occured during sending the email. The email was not sent: " & vbNewLine & Err.Description, vbCritical, "Error " & Err.Number, Err.HelpFile, Err.HelpContext
End Sub
Send multiple different e-mails
To send multiple different e-mails you need to make your procedure a more universal function receiving some parameters.
Public Function SendMyEMail(MailTo As String, MailCC As String, MailSubject As String, MailFileName As String)
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = " Hello"
On Error GoTo MAIL_ERROR 'jump to the error handler if an error occurs
With OutMail
.To = MailTo
.CC = MailCC
.BCC = ""
.Subject = MailSubject
.HTMLBody = strbody
'You can add an attachment like this
.Attachments.Add MailFileName
.send 'or use .Display
End With
On Error GoTo 0 'stop error handling here (no jumps to the error handler anymore.
'The following 2 lines can be omitted because it is done automatically on exit sub
'So these are completely unnecessary.
'Set OutMail = Nothing
'Set OutApp = Nothing
Exit Function 'we need this to not to run into error handler if everything was ok
MAIL_ERROR: 'Show error message
MsgBox "An error occured during sending the email. The email was not sent: " & vbNewLine & Err.Description, vbCritical, "Error " & Err.Number, Err.HelpFile, Err.HelpContext
End Function
And a procedure SendMultipleEmails looping through a worksheet and run SendMyEMail for every row.
Public Sub SendMultipleEmails()
Dim wsMail As Worksheet
Set wsMail = Worksheets("MyMailSheet")
Dim iRow As Long, lRow As Long
lRow = wsMail.Cells(wsMail.Rows.Count, "A").End(xlUp).Row 'find last used row in column A
For iRow = 1 To lRow 'run from first to last used row
SendMyEMail wsMail.Cells(i, "A"), wsMail.Cells(i, "B"), wsMail.Cells(i, "C"), wsMail.Cells(i, "D")
'SendMyEMail for every row in that sheet where MailTo is in column A, MailCC is in column B, …
Next iRow
End Sub
You can check if the file exists before attempting to draft the email.
Sub SendEmail()
'Exit if file does not exist
If Len(Dir("E:\Auto Reports\test.xlsb", vbDirectory)) = 0 Then Exit Sub
'Proceed
Dim OutApp As Object
'rest of code
End Sub

Send an Email using PowerPoint VBA

I want to send an email (with subject, body...) to another email address.
I tried the following code, but it didn't work:
Private Sub CommandButton1_Click()
Dim ret As Boolean
Dim strAddress As String
Dim strMessage As String
strAddress = "examplemail#gmail.com"
ret = SendEMail(strAddress, (Label1.Caption), strMessage)
Label1.Caption = ret
If Label1.Caption = "True" Then
MsgBox "Mail sent!"
ElseIf Label1.Caption = "False" Then
MsgBox "Mail not sent!"
End If
End Sub
Public Function SendEMail(strRecipient As String, strSubject As String, strBody As String) As Boolean
Dim oApp As Object
Dim oMail As Object
Err.Clear
On Error Resume Next
Set oApp = GetObject(Class:="Outlook.Application")
If Err <> 0 Then Set oApp = CreateObject("Outlook.Application")
Err.Clear
Set oMail = oApp.CreateItem(0)
With oMail
.Subject = strSubject
.To = strRecipient
'copy to self
.CC = "youraddy#you.com"
.BodyFormat = 1
.Body = strBody
.Send
End With
'cleanup
Set oMail = Nothing
Set oApp = Nothing
'All OK?
If Err = 0 Then SendEMail = True Else SendEMail = False
End Function
The code was originally taken from here.
If it is possible, I want a code that is compatible with most PCs.
Using Microsoft Outlook
For sending an e-mail you need to have an e-mail account in Microsoft Outlook configured, because your code is using Outlook to send the e-mail.
Set oApp = GetObject(Class:="Outlook.Application")
Alternative 1: SMTP
Alternatively you could set up an SMTP connection in VBA to send the e-mails over an external mail server using CDO. More information on the usage of CDO in VBA can be found here (even if they write the code is for Excel, you can use it for PowerPoint as well) and here as well.
The drawback of this approach is, that the SMTP login credentials are visible in the VBA code. This could be a security issue if you plan to share this presentation with other people.
Alternative 2: Mailto-Link
A third way would be to offer the user a link to click on in order to send the e-mail: mailto:recipient#example.com?subject=xxx
A description for this approach can be found here (scroll down to the third option).

File sent as email attachment via Excel VBA is always corrupt

I'm using the following error handling method to save a copy of the file that's currently open and send it to my email if it causes an error.
Private Declare Function GetTempPath _
Lib "kernel32" Alias "GetTempPathA" _
(ByVal nBufferLength As Long, _
ByVal lpBuffer As String) As Long
Private Const MAX_PATH As Long = 260
Sub MainSub()
Dim OutApp As Object, OutMail As Object
Dim wb As Workbook
On Error GoTo NotifyandRepair
Call Sub1
Call Sub2
Call Subn
Exit Sub
NotifyandRepair:
Set wb = ThisWorkbook
Application.DisplayAlerts = False
wb.SaveAs TempPath & "ErroringFile.xlsx", FileFormat:= _xlNormal,AccessMode:=xlExclusive,ConflictResolution:=Excel.XlSaveConflictResolution.xlLocalSessionChanges
Application.DisplayAlerts = True
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = "name#company.com"
.Subject = "Error Occured - Error Number " & Err.Number
.Body = Err.Description
.Attachments.Add TempPath & "ErroringFile.xlsx"
.Send '~~> Change this to .Display for displaying the email
End With
Set OutApp = Nothing: Set OutMail = Nothing
End Sub
Function TempPath() As String
TempPath = String$(MAX_PATH, Chr$(0))
GetTempPath MAX_PATH, TempPath
TempPath = Replace(TempPath, Chr$(0), "")
End Function
It appears to work fine. When an unhandled error occurs it sends me a copy of the file and its been renamed "ErroringFile.xlsx". The problem is the file is always corrupt.
Am I doing something wrong?
How do I fix this issue so the file isn't corrupt?
It's the wrong FileFormat you SaveAs.
See XlFileFormat Enumeration, you should be saving it as xlOpenXMLWorkbook.

Excel VBA debugging method

i currently have a form with a textbox and a button. you can enter any number in the textbox and when you hit the button it will show the number on a message box, but if there is an error, a message will pop up and you can click the debug button to see which line gave an error. This will be for the code:
On Error GoTo 0:
But if i replace the 0 with "error:", it will take me to a new subroutine that will send me an email regarding the issue but it will not highlight the line which gave me an error when i hit the debug button.
Is there a way i can send myself an email AND when i hit the debug button it will highlight the error line?
Private Sub CommandButton1_Click()
'on error goto error:
On Error GoTo 0:
Dim word As Double
word = TextBox1.Text
MsgBox word
Exit Sub
error:
Call error()
End Sub
Sub error()
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "error"
With OutMail
.To = "blahblah#hotmail.com"
.CC = ""
.BCC = ""
.Subject = "error"
.Body = strbody
.Send
End With
Set OutMail = Nothing
Set OutApp = Nothing
Debug.Assert (Err.Number & Err.Description)
End Sub
The below pattern calls error() then breaks in the IDE on the line that caused the error:
Sub Foo()
On Error GoTo ERR_HANDLER
Dim i As Long
i = i / 0
Exit Sub
ERR_HANDLER:
Call error()
On Error GoTo 0
Resume
End Sub