Managed to get this sending using Excel with SMTP.
When sending one e-mail at a time, the first one has the signature displayed where it should be.
Second e-mail sent has the signature but adds the signature as an attachment.
Third e-mail sent has the signature but adds the signature as an attachment twice, and it will repeat the the cycle adding more signature images as attachments.
TLDR:
1 e-mail sent = 0 attachment
2 e-mails sent = 1 attachment
3 e-mails sent = 2 attachments
I don't want any attached files.
Sub SendMail()
Set MyEmail = CreateObject("CDO.Message")
Path = "C:\Users\Users1\Desktop\Signature\"
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Sheet1")
Set sh2 = ThisWorkbook.Sheets("Sheet2")
Dim nDateTime As Date, oDateTime As Date
nDateTime = Now
oDateTime = nDateTime - 3
Dim last_row As Integer
last_row = Application.CountA(sh.Range("A:A"))
For i = 2 To last_row
Set emailConfig = MyEmail.Configuration
With MyEmail
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/sendusing")
= redacted
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserver")
= redacted
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserverport")
= redacted
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate")
= redacted
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpusessl")
= redacted
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/sendusername")
= redacted
emailConfig.Fields.Update
MyEmail.Configuration.Fields.Update
End With
mail_body_message = sh2.Range("D2")
serial_number = sh.Range("A" & i).Value
mail_body_message = Replace(mail_body_message, "replace_serial_here", serial_number)
Attachment = Path + Filename
signaturelogo = "userSignature.png"
With MyEmail
Attachment = Path + Filename
signaturelogo = "userSignature.png"
Path = "C:\Users\Users1\Desktop\Signature\"
.Subject = "Hello there (HTTPS) Serial: " & serial_number
.From = "redacted"
.To = sh.Range("B" & i).Value
.HTMLBody = mail_body_message
.Attachments.Add Path & signaturelogo, 0
End With
If sh.Range("C" & i).Value <= oDateTime Then
MyEmail.Send
End If
Next i
End Sub
Because you are re-using the same object just attach the logo once at the start.
Option Explicit
Sub SendMyMail()
Const LOGO = "C:\Users\Users1\Desktop\Signature\userSignature.png"
Const DAYS = 3
Const SCHEMA = "http://schemas.microsoft.com/cdo/configuration/"
' configure email
Dim MyEmail As Object
Set MyEmail = CreateObject("CDO.Message")
With MyEmail
With .Configuration.Fields
.Item(SCHEMA & "sendusing") = 2
.Item(SCHEMA & "smtpserver") = "smtp.#.com"
.Item(SCHEMA & "smtpserverport") = 465
.Item(SCHEMA & "smtpauthenticate") = 1
.Item(SCHEMA & "sendusername") = "###"
.Item(SCHEMA & "sendpassword") = "#"
.Item(SCHEMA & "smtpusessl") = 1
.Update
End With
' add logo
.AddAttachment LOGO
End With
Dim sh As Worksheet, sh2 As Worksheet
Dim serialno As String, n As Long, i As Long, last_row As Long
Set sh = ThisWorkbook.Sheets("Sheet1")
Set sh2 = ThisWorkbook.Sheets("Sheet2")
With sh
last_row = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
For i = 2 To last_row
If sh.Range("C" & i).Value <= Now - DAYS Then
serialno = sh.Range("A" & i).Value
With MyEmail
.Subject = "Hello there (HTTPS) Serial: " & serialno
.From = "redacted"
.To = sh.Range("B" & i).Value
.HTMLBody = Replace(sh2.Range("D2"), "replace_serial_here", serialno)
' send
On Error Resume Next
.Send
If Err.Number = 0 Then
n = n + 1
Else
MsgBox Err.Description, vbExclamation, "Error Row " & i
End If
On Error GoTo 0
End With
Else
'Debug.Print "Skipped row " & i & " = " & sh.Range("C" & i)
End If
Next
MsgBox n & " emails sent", vbInformation
End Sub
Ended up removing .Attachments.Add Path & signaturelogo, 0
For .HTMLBody = mail_body_message
Changed to below, (the fix)
.HTMLBody = mail_body_message & " "
Related
I am trying to send email using outlook and vbs.
Parse through excel
take subject, email, name, attachment etc from there. the based on attachment name, i need to insert table from attachment excel into body of email.
set app = CreateObject("Excel.Application")
' get current path
Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
strPath = WshShell.CurrentDirectory
Set WshShell = Nothing
'converting csv to xlsx
Set wb = app.Workbooks.Open (strPath+"\"+"rbo1.csv")
WB.SaveAs Replace(WB.FullName, ".csv", ".xlsx"), 51
WB.Close False
wb.close 0
set wb =nothing
Set wb = app.Workbooks.Open (strPath+"\"+"rbo1.xlsx")
set sh = wb.Sheets(1)
row = 2
set name sh.cells("C" & row)
set email = sh.Range("L" & row)
set subject = sh.Range("M" & row)
set attach = sh.Range("N" & row)
Set Cur_date = sh.range("A" & row)
Set Prev_date = sh.range("B" & row)
Set Prev_Bal = sh.range("G" & row)
Set Cur_Bal = sh.range("H" & row)
LastRow = sh.UsedRange.Rows.Count
For r = row to LastRow
If App.WorkSheetFunction.CountA(sh.Rows(r)) <> 0 Then
SendMessage email, name, subject, TRUE, attach, strPath, Cur_date, Prev_date,_
Prev_Bal , Cur_Bal
row = row + 1
name sh.cells("C" & row)
email = sh.Range("L" & row)
subject = sh.Range("M" & row)
attach = sh.Range("N" & row)
Cur_date = sh.range("A" & row)
Prev_date = sh.range("B" & row)
Prev_Bal = sh.range("G" & row)
Cur_Bal = sh.range("H" & row)
End if
Next
wb.close
set wb = nothing
set app = nothing
Sub SendMessage(EmailAddress, DisplayName, Subject, DisplayMsg, AttachmentPath, strPath, Cur_date, Prev_date, Prev_Bal , Cur_Bal)
' Create the Outlook session.
Set objOutlook = CreateObject("Outlook.Application")
objXl = app.Workbooks.Open(strPath+"\"+AttachmentPath)
htmlmsg = extracttablehtml(objXl.worksheets(1), objXl.worksheets(1).usedRange)
' Create the message.
Set objOutlookMsg = objOutlook.CreateItem(0)
With objOutlookMsg
' Add the To recipient(s) to the message.
Set objOutlookRecip = .Recipients.Add(EmailAddress)
objOutlookRecip.resolve
objOutlookRecip.Type = 1
' Set the Subject, Body, and Importance of the message.
.Subject = Subject
.bodyformat = 3
.Importance = 2 'High importance
.HTMLBody = "<table> <br> Dear Sir, <br><br> given under details the change balance+"<br> for any query please call under signed<br><br>" + htmlmsg
' Should we display the message before sending?
If DisplayMsg Then
.Display
Else
.Save
' .Send
End If
End With
objXl.close 0
set objXl = Nothing
Set objOutlook = Nothing
End Sub
Function extracttablehtml(ws, rng)
Dim HtmlContent
Dim i
Dim j
On Error GoTo 0
HtmlContent = "<table>"
For i = 1 To rng.Rows.Count
HtmlContent = HtmlContent & "<tr>"
For j = 1 To rng.Columns.Count
HtmlContent = HtmlContent & "<td>" & ws.Cells(i, j).Value & "</td>"
Next
HtmlContent = HtmlContent & "</tr>"
Next
HtmlContent = HtmlContent & "</table>"
extracttablehtml = HtmlContent
End Function
two problems
extracttablehtml is not working as desired please advise whats the problem
now modification i need to do is to choose only rows based on given criteria
thanks in advance
The below code sends emails from my Excel file.
However I do not know where to add the .sentonbehalfof line to send from a specific shared mailbox that I have permission to send from.
Sub send_email()
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Statements")
Dim OA As Object
Dim msg As Object
Set OA = CreateObject("Outlook.Application")
Dim each_row As Integer
Dim last_row As Integer
last_row = Application.WorksheetFunction.CountA(sh.Range("A:A"))
For each_row = 2 To last_row
Set msg = OA.createitem(0)
msg.To = sh.Range("A" & each_row).Value
first_name = sh.Range("B" & each_row).Value
last_name = sh.Range("C" & each_row).Value
msg.cc = sh.Range("D" & each_row).Value
msg.Subject = sh.Range("E" & each_row).Value
msg.body = sh.Range("F" & each_row).Value
date_to_send = sh.Range("H" & each_row).Value
date_to_send = Format(date_to_send, "dd/mm/yyyy")
Status = sh.Range("I" & each_row).Value
current_date = Format(Date, "dd/mm/yyyy")
If date_to_send = current_date Then
If sh.Range("G" & each_row).Value <> "" Then
msg.attachments.Add sh.Range("G" & each_row).Value
Cells(each_row, 9).Value = "Sent"
Content = Replace(msg.body, "<>", first_name + " " + last_name)
msg.body = Content
msg.send
Else
Cells(each_row, 9).Value = "Sent"
Content = Replace(msg.body, "<>", first_name + " " + last_name)
msg.body = Content
msg.send
End If
End If
Next each_row
End Sub
Try adding
msg.SentOnBehalfOfName = "Your shared email address"
above this line
msg.cc = sh.Range("D" & each_row).Value
It worked for me!
I have the following list with one, or multiple entries for a specific ID.
I have a second list with with unique IDs and email addresses.
I need to loop through the list, send an email to every ID and list data from each matching row in the email, also mentioning the total amount.
Example of the email sent to ID 1234 foo#bar.com:
What I have so far:
Sub SendEmail()
Dim strbody1 As String
Dim strbody2 As String
Dim Signature As String
Dim i As Integer, Mail_Object, Email_Subject, o As Variant, lr As Long
lr = Cells(Rows.Count, "A").End(xlUp).Row
strbody1 = "Hi,<br><br>" & _
"Test.<br><br>"
strbody2 = "Test1.<br><br>" & _
"Foobar,"
Signature = "<H4><B>My Name</B></H4>" & _
"Something<br>" & _
"Something<br>" & _
"T: +1 000 000 000<br>" & _
"foo#bar.com<br>" & _
"www.bar.com"
If MsgBox(("This will send all emails in the list. Do you want to proceed?"), vbYesNo) = vbNo Then Exit Sub
Set Mail_Object = CreateObject("Outlook.Application")
For i = 2 To lr
With Mail_Object.CreateItem(o)
.Subject = Range("B" & i).Value
.SentOnBehalfOfName = "foo#bar.com"
.To = Range("A" & i).Value
.Body = Range("C" & i).Value
.HTMLBody = strbody1 & strbody2 & Signature
.Send 'disable display and enable send to send automatically
End With
Next i
MsgBox "E-mail successfully sent", 64
Application.DisplayAlerts = False
Set Mail_Object = Nothing
End Sub
You can put the IDs into a Dictionary Object. Then scan the data for each ID in turn adding the rows with that ID to an html table. If performance is an issue copy the data to an array first and scan that.
Option Explicit
Sub SendEMail()
Const WS_ID = "Sheet1"
Const WS_DATA = "Sheet2"
Const HEAD = "<head><style>body {font: 20px Verdana;} " & _
" .amount {text-align:right;}</style></head>"
Const TABLE = "<table cellspacing=""0"" cellpadding=""5""" & _
" border=""1"">" & _
"<tr bgcolor=""#EEEEEE""><th>REF</th><th>Amount</th></tr>"
Const TXT = "This is a test email"
Dim wb As Workbook, ws As Worksheet
Dim iLastRow As Long, i As Long
Dim dictID As Object, ID, addr As String
Set dictID = CreateObject("Scripting.Dictionary")
' get list of IDS
Set wb = ThisWorkbook
Set ws = wb.Sheets(WS_ID)
iLastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row
For i = 2 To iLastRow
ID = Trim(ws.Cells(i, "A"))
addr = Trim(ws.Cells(i, "B"))
If dictID.exists(ID) Then
MsgBox ID & " is duplicated", vbCritical, "Duplicate ID"
Exit Sub
ElseIf InStr(1, addr, "#") > 0 Then
dictID.Add ID, addr
End If
Next
Dim objOut
Set objOut = CreateObject("Outlook.Application")
' scan data
Dim total As Double, htm As String
Set ws = wb.Sheets(WS_DATA)
iLastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row
For Each ID In dictID
total = 0
addr = dictID(ID)
' build html table
htm = "<html>" & HEAD & "<body><p>" & TXT & "</p>" & TABLE
For i = 2 To iLastRow
If ws.Cells(i, "A") = CStr(ID) Then
htm = htm & "<tr><td>" & ws.Cells(i, "B") & _
"</td><td class=""amount"">" & ws.Cells(i, "C") & "</td></tr>" & vbCrLf
total = total + ws.Cells(i, "C")
End If
Next
total = Format(total, "#,##0")
htm = htm & "<tr bgcolor=""#CCFFCC"" style=""font-weight:bold""><td>TOTAL</td>" & _
"<td class=""amount"">" & total & "</td></tr></table><br/>" & _
"<p>The total amount is " & total & "</p></body></html>"
' send email
Call SendOneEMail(objOut, CStr(ID), addr, htm)
Next
MsgBox dictID.Count & " emails sent", vbInformation
End Sub
Sub SendOneEMail(objOut, sID As String, sTo As String, htm As String)
' create email
With objOut.CreateItem(0) 'olMailItem
.Subject = sID
.SentOnBehalfOfName = "foo#bar.com"
.To = sTo
.HTMLBody = htm
.Display
'.Send 'disable display and enable send to send automatically
End With
End Sub
Trying to send emails using VBA however it keeps sending from my personal email address despite best efforts. Please can someone advise how to send from secondary email address?
Sub Send_Mail()
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Send_Mail")
Dim I As Integer
Dim OA As Object
Dim msg As Object
Set OA = CreateObject("outlook.application")
Set OutAccount = OA.Session.Accounts.Item(2)
Dim last_row As Integer
last_row = Application.CountA(sh.Range("A:A"))
For I = 2 To last_row
Set msg = OA.CreateItem(0)
msg.SendUsingAccount = OutAccount
msg.To = sh.Range("B" & I).Value
msg.cc = sh.Range("D" & I).Value
msg.Subject = sh.Range("E" & I).Value
msg.body = sh.Range("F" & I).Value
If sh.Range("G" & I).Value <> "" Then
msg.attachments.Add sh.Range("G" & I).Value
End If
msg.send
sh.Range("H" & I).Value = "Sent"
Next I
MsgBox "All emails sent successfully"
End Sub
Thank you!
You can use .From to set the email account that you want to send it from.
strFrom = Name & "<" & Email & ">"
msg.From = strFrom
I'm trying to send emails to each student contain the (student name and his marks ) using VBA ..
I have excel sheet as below
From above excel i need to send email to each student with email body text as below
Hi " Student name "
Below you can found your marks:-
Math :- " his mark"
Network :- "his mark"
Physics :- "his mark"
Antenna :- " his mark"
I already wort the code in VBA , but i don't know how send like this text to each student in the mailBody section ..
My code as below
Sub SendMail()
Dim objEmail
Const cdoSendUsingPort = 2 ' Send the message using SMTP
Const cdoBasicAuth = 1 ' Clear-text authentication
Const cdoTimeout = 100 ' Timeout for SMTP in seconds
mailServer = "smtp.gmail.com"
SMTPport = 465 '25 'SMTPport = 465
mailusername = Range("j9").Value
mailpassword = Range("j10").Value
''''''''
Dim n As Integer
n = Application.WorksheetFunction.CountA(Range("c:c")) - 1
For i = 1 To n
mailto = Range("c1").Offset(i, 0).Value
mailSubject = Range("e1").Offset(i, 0).Value
**mailBody = ??** What i should to set ?
Set objEmail = CreateObject("CDO.Message")
Set objConf = objEmail.Configuration
Set objFlds = objConf.Fields
With objFlds
.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = cdoSendUsingPort
.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = mailServer
.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = SMTPport
.Item("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = True
.Item("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout") = cdoTimeout
.Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = cdoBasicAuth
.Item("http://schemas.microsoft.com/cdo/configuration/sendusername") = mailusername
.Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") = mailpassword
.Update
End With
objEmail.To = mailto
objEmail.From = mailusername
objEmail.subject = mailSubject
objEmail.TextBody = mailBody
'objEmail.AddAttachment "C:\report.pdf"
objEmail.CC = Range("d1").Offset(i, 0).Value
objEmail.BCC = Range("k1").Offset(i, 0).Value
objEmail.Send
Set objFlds = Nothing
Set objConf = Nothing
Set objEmail = Nothing
Next i
End Sub
Kind Regards..
Try this approach, please:
mailBody = "Hy " & Range("B" & i) & "," & vbCrLf & vbCrLf & _
"Below you can find your marks:" & vbCrLf & vbCrLf & _
"Network: - " & Range("G" & i) & vbCrLf & _
"Physics: - " & Range("H" & i) & vbCrLf & _
"Antenna: - " & Range("I" & i)
And start the iteration from 2:
For i = 2 To n
Then no need to any Offset:
objEmail.CC = Range("d" & i).Value
objEmail.BCC = Range("k" & i).Value