I have come across an issue when sending SMTP email, to a number of email address approx. 200. I am looking for a script in which it reads a .txt file containing the 200 email addresses and in smaller batches, sends an generic SMTP message using the script below.
The script which sends the generic email is below:
$to = "TO EMAIL"
$smtp = "SMTP Server"
$from = "FROM EMAIL"
$subject = "Subject"
$body = "EMAIL BODY"
send-MailMessage -SmtpServer $smtp -To $to -Bcc (Get-Content "\\FILE Location") -From $from -Subject $subject -Body $body -BodyAsHtml -Priority high
Any help would be appreciated.
Here's one solution (there might be other/better ways):
$to = "TO EMAIL"
$smtp = "SMTP Server"
$from = "FROM EMAIL"
$subject = "Subject"
$body = "EMAIL BODY"
$Recipient = Get-Content "emails.txt"
$NumberOfBatches = [int]($Recipient.count / 50)
For ($i = 0; $i -lt $NumberOfBatches; $i++) {
$Emails = $Recipient | Select -First 50 -Skip ($i * 50)
Send-MailMessage -SmtpServer $smtp -To $to -Bcc $Emails -From $from -Subject $subject -Body $body -BodyAsHtml -Priority high
}
This loads the list of emails address in to a variable named $Recipient.
It then gets a count for how many batches there would need to be to send it 50 emails at a time, casting this as [int] to get a round number.
It then uses a For loop to do the number of batches defined, and uses the Select-Object cmdlet to filter the list of emails by the defined batches, by using -First and -Skip.
Related
I have a task to send some 500 e-mails and I'm exploring the best (easiest) way to do that. I came across some Powershell examples but I can't make it work. I see there are 2 approaches: create a script and then call it from powershell command line, or do it directly from command line. The second approach would be better for me because it would be easier to generate those command lines for 500 e-mails. I found some examples and come to this:
$smtp = New-Object Net.Mail.SmtpClient("smtp.gmail.com", "465")
$Smtp.EnableSsl = $true
$Smtp.Credentials = New-Object System.Net.NetworkCredential("myusername","mypass")
$Smtp.Attachments.Add("C:\bla.txt")
$smtp.Send("myusername#gmail.com","someusername#gmail.com","Test Email","This is a test")
For the first attempt I'm trying to send mail from gmail...
I'm not good in Powershell (better to say, don't know it at all but have some general knowledge about command line from command prompt/MS-DOS which is more familiar to me).
Also will, mail server allow sending 500 e-mails like this or it will recognize it as some attack, spam, whatever...?
I would appreciate any help.
Thanks!
EDIT:
I have also tried this:
$From = "YourEmail#gmail.com"
$To = "AnotherEmail#YourDomain.com"
$Cc = "YourBoss#YourDomain.com"
$Subject = "Email Subject"
$Body = "Insert body text here"
$SMTPServer = "smtp.gmail.com"
$SMTPPort = "465"
Send-MailMessage -From $From -to $To -Cc $Cc -Subject $Subject -Body $Body -SmtpServer $SMTPServer -port $SMTPPort -UseSsl -Credential (Get-Credential)
For $From, $To, $Cc I have put my real e-mail address
Error I got is this:
Send-MailMessage : Unable to read data from the transport connection: net_io_connectionclosed.
At line:9 char:1
+ Send-MailMessage -From $From -to $To -Cc $Cc -Subject $Subject -Body ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpException
+ FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage
According to Gmail's Support Page Gmail's limit on the the number of emails sent via the SMTP relay service (for G Suite accounts) is 10,000 emails every 24 hours. If you exceed the limit, you will receive an HTTP 550 error and will be banned from sending emails for the next 24 hours. If you do not have a G Suite account, the limit is 500 per 24 hours. Exceeding this also will result in a 550 error and a 24 hour ban from use of Gmail. Also, Gmail only allows non-G Suite users to send emails to 100 recipients per email over the SMTP relay, so if you did send the email to your email list it would have to be split into multiple emails.
As such, I would not recommend sending your 500+ emails via Google's SMTP service unless you have G Suite account, as it may have your account disabled for 24 hours and any messages sent past the 500 email limit will be blocked.
(I think think you can use your company's email server or some server let you send more than 500 email.)
Setting your gmail smtp server. You will get a application password.
encryption your password
Read-Host "Enter gmail application password" -AsSecureString | ConvertFrom-SecureString | Out-File "$HOME\Desktop\SendEmailUse.txt"
Than you can send email (auto login)
$emailFrom = "sendFrom#gmail.com"
$sendto = "sendTo-1#gmail.com"
$sendto2 = "sendTo-2#yahoo.com.tw" # -cc -bcc
$runDateTime = Get-Date
$Subject = "Script Run Completed - $runDateTime" # title
$attachmentLocation = "$HOME\Desktop\ScheduledJobLog.txt" # -Attachments
$emailBody = #"
This is PowerShell sent mail test.
at $runDateTime
"#
$pwdfile = "$HOME\Desktop\SendEmailUse.txt"
$emailSmtpServer = "smtp.gmail.com"
$port = "587"
$pwd = (Get-Content $pwdfile | ConvertTo-SecureString)
$creds = New-Object System.Management.Automation.PSCredential($emailFrom, $pwd)
Send-MailMessage -From $emailFrom -To $sendto -Cc $sendto2 -SmtpServer $emailSmtpServer -Port $port -Credential $creds -UseSsl -Body $emailBody -Encoding 'utf8' -Subject $Subject -Attachments $attachmentLocation
Write-Output "Email Sented."
The variable $reperr is not expanding inside the double quoted here-string. When the scriptblock completes, $reperr does have a value, but it will not print in the here string, all i get in the body is the flat text "There are currently errors with domain.com AD replication."
Clear-Variable -name "reperr"
$reperr = Get-ADReplicationPartnerMetadata -target * |? {$_.ConsecutiveReplicationFailures -eq "0"} |select Server, ConsecutiveReplicationFailures
$smtpserver = "10.25.172.2"
#$recipients = "email#emailaddy.com"
$recipients = "user#doamin.com"
$sender = "ad_repl_status#domain.com"
$subject = "DOMAIN.COM ACTIVE DIRECTORY REPLICATION ISSUES DETECTED!"
$body = #"
There are currently errors with domain.com AD replication.
$reperr
"#
if (!$reperr)
{
Write-Host "AD REPLICATION IS CLEAN"
}
else
{
Send-MailMessage -Priority High -SmtpServer $smtpserver -From $sender -To $recipients -Subject $subject -Body $body
}
While trying to attach the .CSV file and run the code, i get the error as "Exception calling "Send" with "1" argument(s): "Unable to send to all recipients."
I have tried with .txt file ($attachment = "\path1\test.txt") and the same code is executed without any error (but I have not received any mail)
$date_value = Get-Date -format yyyy_MM_dd
$file_Name = 'test_'+ $date_value.ToString() + '.csv'
$attachment = "\\path1\test.CSV"
$smtpserver = "server.com"
$size=((Get-item $attachment ).length) -as [Int]
$from = "mail.com"
[string[]]$To= "xyz#xyz.com"
$CC="xyz#xyz.com"
$Subject = "Test"
$body=#"
Hi,
Test
Regards,
Team
"#
$message = new-object System.Net.Mail.MailMessage ( $From , $To )
$message.CC.Add($cc)
$message.Subject = $Subject
$attach = new-object Net.Mail.Attachment($attachment)
$message.Attachments.Add($attach)
$message.body = $body
$smtp = new-object Net.Mail.SmtpClient($smtpserver)
if ($size -gt 0){
$smtp.Send($message)
}
$attach.Dispose()
$message.Dispose()
$smtp.Dispose()
Expectation: .CSV file should get attached and send in the email
Have you tried the Send-MailMessage cmdlet with the -Attachment option? Its really simple.
Send-MailMessage -To $To -From $from -Cc $CC -Subject $Subject -Attachments $attachment -Body $body -SmtpServer $smtpserver
I have a sharepoint list that has a people column - I am trying to write a PS script that would email a person in the people column. Now the problem I am facing is I can't substitute a list variable into the send-mailmessage cmdlet i/e the following does not work:
cls
if((Get-PSSnapin | Where {$_.Name -eq "Microsoft.SharePoint.PowerShell"}) -eq $null) {
Add-PSSnapin Microsoft.SharePoint.PowerShell;
}
$sourceWebURL = "http://sp2k10lab"
$sourceListName = "miztest"
$spSourceWeb = Get-SPWeb $sourceWebURL
$spSourceList = $spSourceWeb.Lists[$sourceListName]
$spSourceItems = $spSourceList.GetItems()
$spSourceItems | ForEach-Object {
$_name=$_['name']
$_email=$_['email']
send-mailmessage -from "support#XXXXXX" -to $_email -subject "Regulatory Reminder Notice" -body "Tboooooooooooooooooooooooooitle is overdue by $_diff days" -priority High -dno onSuccess, onFailure -smtpServer XXXXXXXx
}
$_email is where the email address is stored in the list - however - when I try to substitute it into my send-mailmessage cmdlet it does not - the sendmail-message cmdlet works only if I explicitly set an email addy in there i.e the following works
send-mailmessage -from "support#XXXXXX" -to "foo_miz <'abc#XXXXX.com'>" -subject "Regulatory Reminder Notice" -body "Tboooooooooooooooooooooooooitle is overdue by $_diff days" -priority High -dno onSuccess, onFailure -smtpServer XXXXXXX
Should I be using a different cmdlet for this purpose - or is this just me being silly with my syntax?
Thanks for any help - would really appreciate a way to do this.
First of all you should not use the '_' character at the begining of your vars, just becaise $_ is a specific var in PowerShell.
Second, here is the way I use Send-MailMessage and it works :
$mailServer = "smtp.myserver.com"
$encoding=[System.Text.Encoding]::UTF8
$cred = $null
$body = "Are you serious !"
$DesAdressesDest = "Nicolas S <nicolas.sc#Elyse.fs>","Francois H <francois.h#Elyse.fr>"
$Subject = "About French bashing"
send-mailmessage -SmtpServer $mailServer `
-to $DesAdressesDest `
-from "JP Blanc <jpb#people.com>"`
-subject $Subject `
-body $Body -BodyAsHtml `
-ErrorAction continue `
-Encoding $encoding
I am using send-mail message to send email to our Support System.
But when it send email it shows the subject line like this screen!
=?us-ascii?Q?R899076:Aman:System Summary ?=
In Subject I am using the variable:
$vUserName = (Get-Item env:\username).Value
$vComputerName = (Get-Item env:\Computername).Value
$subject = "$vComputerName : $vUserName : System Summary"
and then
send-MailMessage -SmtpServer Smtp-local -To $to -From $from -Subject $subject -Body $body -BodyAsHtml -Priority High
But when I recieve this email in Outlook it looks fine any Idea?
Actually this a approx 150 lines script and the body of email and smtp server are already specified in the server.
yes I tried the $subject = "$env:ComputerName : $env:UserName : System Summary" variable and the result is same.
yes I have tried the - encoding option and it gives an error
Send-MailMessage : Cannot bind parameter 'Encoding'. Cannot convert the "utf8" value of type "Syste
m.String" to type "System.Text.Encoding".
At D:\PowerShell\MyScripts\SystemInfo\SysInfo-V6-test[notfinal].ps1:151 char:84
+ send-MailMessage -SmtpServer $smtp -To $to -From $from -Subject $subject -Encoding <<<< utf8 -B
ody $body -Attachments "$filepath\$name.html" -BodyAsHtml -Priority High
+ CategoryInfo : InvalidArgument: (:) [Send-MailMessage], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.SendMai
lMessage
Any clue?
You could write a custom function to send using .net instead of using the Send-MailMessage cmdlet. It's a lot clunkier, but gets round the problem.
Something like this:
Function SendEmail ($emailFrom, $emailTo, $subject, $body, $attachment) {
# Create from/to addresses
$from = New-Object System.Net.Mail.MailAddress $emailFrom
$to = New-Object System.Net.Mail.MailAddress $emailTo
# Create Message
$message = new-object System.Net.Mail.MailMessage $from, $to
$message.Subject = $subject
$message.Body = $body
$attachment = new-object System.Net.Mail.Attachment($attachment)
$message.Attachments.Add($attachment)
# Set SMTP Server and create SMTP Client
$server = <your server>
$client = new-object system.net.mail.smtpclient $server
# Send the message
"Sending an e-mail message to {0} by using SMTP host {1} port {2}." -f $to.ToString(), $client.Host, $client.Port
try {
$client.Send($message)
"Message to: {1}, from: {0} has beens successfully sent" -f $from, $to
}
catch {
"Exception caught in CreateTestMessage: {0}" -f $Error.ToString()
}
}
(Thanks to Thomas Lee (tfl#psp.co.uk) - I tweaked this from his code at http://powershell.com/cs/media/p/357.aspx)
The Send-MailMessage cmdlet doesn't have any output after you send emails, I wonder where the output comes from? Can you include the command you use and the output?
As to your subject line, you can reduce it to one line only:
$subject = "$env:ComputerName : $env:UserName : System Summary"
The Send-MailMessage has an Encoding parameter, have you tried it?
This happened to me when I used Send-MailMessage with the default encoding (ASCII) when there were spaces in the subject.
First, to answer the question about the Encoding parameter: You are trying to pass it as a string (ie "-Encoding ASCII"), when you should be using this type of syntax instead: "-Encoding ([System.Text.Encoding]::ASCII)".
This "encoding in the subject" issue happened to me, and I narrowed it down to spaces in the subject. To demonstrate:
This will not contain encoding in the subject:
Send-MailMessage -To "alice#example.com" -From "bob#example.com" -Smtp "localhost" -Subject "one" -BodyAsHtml "body1" -Encoding ([System.Text.Encoding]::ASCII)
But this will:
Send-MailMessage -To "alice#example.com" -From "bob#example.com" -Smtp "localhost" -Subject "one two" -BodyAsHtml "body1" -Encoding ([System.Text.Encoding]::ASCII)
Note that the only material difference is the space in the subject.
If I specify UTF8 as the encoding, there is no encoding in the subject:
Send-MailMessage -To "alice#example.com" -From "bob#example.com" -Smtp "localhost" -Subject "one" -BodyAsHtml "body1" -Encoding ([System.Text.Encoding]::UTF8)
But as you say, it looks fine in Outlook, so I presume that the subject is correct. I'm not an expert on email formats or text-encoding, so I won't speculate as to why.