Sending email with CDO.Message using Office 365 SMTP

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
JoeWinograd
Posts: 2177
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Sending email with CDO.Message using Office 365 SMTP

Post by JoeWinograd » 20 Aug 2019, 19:56

Hi Folks,

I've been using this subroutine very successfully for many years with Gmail SMTP:

Code: Select all

pmsg:=ComObjCreate("CDO.Message")
pmsg.From:="[email protected]"
pmsg.To:="[email protected]"
pmsg.Subject:="Hello"
pmsg.TextBody:="World"
fields:=Object()
fields.smtpserver:="smtp.gmail.com"
fields.smtpserverport:=465
fields.smtpusessl:=True
fields.sendusing:=2
fields.smtpauthenticate:=1
fields.sendusername:="[email protected]"
fields.sendpassword:="password"
fields.smtpconnectiontimeout:=60
schema:="http://schemas.microsoft.com/cdo/configuration/"
pfld:=pmsg.Configuration.Fields
For field,value in fields
  pfld.Item(schema . field):=value
pfld.Update()
pmsg.Send()
Return
It also works fine with my personal domain SMTP and my company domain SMTP (with, of course, the proper SMTP settings). However, I'm trying to get it to work with Office 365 SMTP and can't. I've tried this, which contains the values that are supposed to work with Office 365 (smtp.office365.com, port 587):

Code: Select all

SendEmail:
pmsg:=ComObjCreate("CDO.Message")
pmsg.From:="[email protected]"
pmsg.To:="[email protected]"
pmsg.Subject:="Hello"
pmsg.TextBody:="World"
fields:=Object()
fields.smtpserver:="smtp.office365.com"
fields.smtpserverport:=587
fields.smtpusessl:=True
fields.sendusing:=2
fields.smtpauthenticate:=1
fields.sendusername:="[email protected]"
fields.sendpassword:="password"
fields.smtpconnectiontimeout:=60
schema:="http://schemas.microsoft.com/cdo/configuration/"
pfld:=pmsg.Configuration.Fields
For field,value in fields
  pfld.Item(schema . field):=value
pfld.Update()
pmsg.Send()
Return
I also tried port 465, as well as various values for smtpusessl, sendusing, and smtpauthenticate, but I can't find anything that works. Anyone know the right params to use? Or have different AutoHotkey code for sending email that works with Office 365 SMTP? Thanks, Joe

User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Sending email with CDO.Message using Office 365 SMTP

Post by jNizM » 26 Aug 2019, 07:50

As far as I rembember, CDO does not (official) support TLS over 587.

edit:
found (here) an undocumented setting for TLS over 587. can you try it?
fields.sendtls:= True
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile

User avatar
JoeWinograd
Posts: 2177
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Sending email with CDO.Message using Office 365 SMTP

Post by JoeWinograd » 27 Aug 2019, 01:40

Hi jNizM,

Thanks for jumping in...much appreciated!

> As far as I remember, CDO does not (official) support TLS over 587.

After a week at this, I'm now pretty convinced that that's the case.

> undocumented setting for TLS over 587. can you try it?
fields.sendtls:= True

I found that before posting here, but as far as I can tell, the fields.smtpusetls field does not seem to exist. I can't find it (or the named constant cdoSMTPUseTLS) documented in the CDO Namespace, and using it in the AutoHotkey script (set to True or 1) doesn't work.

Edit: I re-read this post after submitting it and noticed that your idea is fields.sendtls, whereas the one I found is fields.smtpusetls. I'll test yours as soon as I can, but the problem right now is that I can't do anything on O365 because Microsoft has blocked my account...got an email that says: "We noticed some unusual activity in your Outlook.com account. To help protect you, we've temporarily blocked your account." Too much email sending while testing, I guess...and I haven't been able to unblock it yet. End Edit.

I also found a post with pmsg.SendTLS() in it...did not work.

I even tried port 25, as there are many posts of success with it a few years ago with smtp.office365.com, but it failed for me. My first guess was that Microsoft shut it down since so many ISPs now block 25 (most email sending has transitioned from 25 to 465 and 587), but a member at another user forum says that 25 works for him now, so I suppose that it is my ISP blocking it. In any event, port 25 is not a viable long term solution.

Another thought was that Office 365 switched to NTLM authentication. I played with that for an hour...no joy.

Then that same member at another user forum that I mentioned above said that he stopped using CDO and moved to PowerShell's Send-MailMessage because CDO was removed from Exchange systems. As I know virtually nothing about PowerShell, he wrote some PowerShell code for me that I was able to incorporate into my AutoHotkey script. For anyone interested, here's a working AutoHotkey script with that member's PowerShell code in it:

Code: Select all

PSexe:="powershell.exe"
EmailSubject:="PowerShell Send-MailMessage in AutoHotkey script"
EmailBody:="The time is: " . A_Now

; Office365
EmailFrom:="[email protected]"
EmailTo:="[email protected]"
EmailPassword:="YourOutlookPassword"
SMTPserver:="smtp.office365.com"
SMTPport:="587"

; Gmail
EmailFrom:="[email protected]"
EmailTo:="[email protected]"
EmailPassword:="YourGmailPassword"
SMTPserver:="smtp.gmail.com"
SMTPport:="587"

PScmd:="""" . "Send-MailMessage -From '" . EmailFrom . "' -to '" . EmailTo . "' -Subject '" . EmailSubject . "' -Body '" . EmailBody
            . "' -SmtpServer '" . SMTPserver . "' -port '" . SMTPport . "' -UseSsl -Credential (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ('"
            . EmailFrom . "', (ConvertTo-SecureString -String '" . EmailPassword . "' -AsPlainText -Force)))" . """"
Run,%PSexe% -command %PScmd%,,Hide
ExitApp
It works with both O365 and Gmail SMTP on port 587.

I've stopped trying to get the CDO code to work, but will certainly be happy to test any other ideas for it. Thanks, Joe

User avatar
JoeWinograd
Posts: 2177
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Sending email with CDO.Message using Office 365 SMTP

Post by JoeWinograd » 27 Aug 2019, 17:27

Hi jNizM,

My Outlook/Office365 account was unblocked and I gave your idea a try with these values:

Code: Select all

fields.smtpserver:="smtp.office365.com"
fields.smtpserverport:="587"
fields.sendtls:=True
fields.sendusing:=2 ; SMTP over the network
fields.smtpauthenticate:=1 ; basic/clear-text authentication
It gives this error:

Code: Select all

Error: 0x8004020E - Cannot modify or delete an object that
was added using the COM+ Admin SDK

Source: (null)

Description: The server rejected the sender address. The
server response was: 530 5.7.57 SMTP; Client was not
authenticated to send anonymous mail during MAIL FROM
[<REDACTED>.prod.outlook.com]

HelpFile:   (null)

HelpContext:  0

Specifically: Send

  Line#
  023: fields.sendpassword:=EmailPassword
  024: fields.smtpconnectiontimeout:=60
  025: schema := "http://schemas.microsoft.com/cdo/configuration/"
  026: pfld := pmsg.Configuration.Fields
  027: For field,value in fields
  028: pfld.Item(schema . field):=value
  029: pfld.Update()
--->  030: pmsg.Send()
  031: Return
  032: Exit
  033: Exit
  033: Exit
Thanks for the idea, but no joy. Btw, the PowerShell code in the AutoHotkey script is working fine now that the account is unblocked. Regards, Joe

User avatar
labrint
Posts: 379
Joined: 14 Jun 2017, 05:06
Location: Malta

Re: Sending email with CDO.Message using Office 365 SMTP

Post by labrint » 26 May 2021, 10:54

This code is fantastic. It works with office 365.

The problem is, how do insert HTML and CSS in the body of the email?
JoeWinograd wrote:
27 Aug 2019, 01:40
Hi jNizM,

Thanks for jumping in...much appreciated!

> As far as I remember, CDO does not (official) support TLS over 587.

After a week at this, I'm now pretty convinced that that's the case.

> undocumented setting for TLS over 587. can you try it?
fields.sendtls:= True

I found that before posting here, but as far as I can tell, the fields.smtpusetls field does not seem to exist. I can't find it (or the named constant cdoSMTPUseTLS) documented in the CDO Namespace, and using it in the AutoHotkey script (set to True or 1) doesn't work.

Edit: I re-read this post after submitting it and noticed that your idea is fields.sendtls, whereas the one I found is fields.smtpusetls. I'll test yours as soon as I can, but the problem right now is that I can't do anything on O365 because Microsoft has blocked my account...got an email that says: "We noticed some unusual activity in your Outlook.com account. To help protect you, we've temporarily blocked your account." Too much email sending while testing, I guess...and I haven't been able to unblock it yet. End Edit.

I also found a post with pmsg.SendTLS() in it...did not work.

I even tried port 25, as there are many posts of success with it a few years ago with smtp.office365.com, but it failed for me. My first guess was that Microsoft shut it down since so many ISPs now block 25 (most email sending has transitioned from 25 to 465 and 587), but a member at another user forum says that 25 works for him now, so I suppose that it is my ISP blocking it. In any event, port 25 is not a viable long term solution.

Another thought was that Office 365 switched to NTLM authentication. I played with that for an hour...no joy.

Then that same member at another user forum that I mentioned above said that he stopped using CDO and moved to PowerShell's Send-MailMessage because CDO was removed from Exchange systems. As I know virtually nothing about PowerShell, he wrote some PowerShell code for me that I was able to incorporate into my AutoHotkey script. For anyone interested, here's a working AutoHotkey script with that member's PowerShell code in it:

Code: Select all

PSexe:="powershell.exe"
EmailSubject:="PowerShell Send-MailMessage in AutoHotkey script"
EmailBody:="The time is: " . A_Now

; Office365
EmailFrom:="[email protected]"
EmailTo:="[email protected]"
EmailPassword:="YourOutlookPassword"
SMTPserver:="smtp.office365.com"
SMTPport:="587"

; Gmail
EmailFrom:="[email protected]"
EmailTo:="[email protected]"
EmailPassword:="YourGmailPassword"
SMTPserver:="smtp.gmail.com"
SMTPport:="587"

PScmd:="""" . "Send-MailMessage -From '" . EmailFrom . "' -to '" . EmailTo . "' -Subject '" . EmailSubject . "' -Body '" . EmailBody
            . "' -SmtpServer '" . SMTPserver . "' -port '" . SMTPport . "' -UseSsl -Credential (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ('"
            . EmailFrom . "', (ConvertTo-SecureString -String '" . EmailPassword . "' -AsPlainText -Force)))" . """"
Run,%PSexe% -command %PScmd%,,Hide
ExitApp
It works with both O365 and Gmail SMTP on port 587.

I've stopped trying to get the CDO code to work, but will certainly be happy to test any other ideas for it. Thanks, Joe

User avatar
JoeWinograd
Posts: 2177
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Sending email with CDO.Message using Office 365 SMTP

Post by JoeWinograd » 02 Jun 2021, 12:56

labrint wrote:It works with office 365.
Glad to hear it! Btw, sorry for the tardy reply on this...I don't recollect receiving a notification on it, although it's certainly possible that I missed it.
labrint wrote:The problem is, how do insert HTML and CSS in the body of the email?
Sorry...can't help you with that...I have little knowledge of HTML and no knowledge of CSS. Regards, Joe

User avatar
labrint
Posts: 379
Joined: 14 Jun 2017, 05:06
Location: Malta

Re: Sending email with CDO.Message using Office 365 SMTP

Post by labrint » 03 Jun 2021, 09:39

JoeWinograd wrote:
02 Jun 2021, 12:56
labrint wrote:It works with office 365.
Glad to hear it! Btw, sorry for the tardy reply on this...I don't recollect receiving a notification on it, although it's certainly possible that I missed it.
labrint wrote:The problem is, how do insert HTML and CSS in the body of the email?
Sorry...can't help you with that...I have little knowledge of HTML and no knowledge of CSS. Regards, Joe
I have solved it with the following code. The trick is to replace -Body with -BodyAsHtml and of course attach the variable as such:

Code: Select all

EmailBody = 
(
<html> " %Head% "
<body>
<div>
<p>" %EmailDate% "<br>" %EmailTime% "</p>
<p>" %BODY% "</p>
<p>" %CLOSING% "</p>
<h2> " %END% %EmailLink% "<br><br>" %PictureLink% "</h2>
</div>
</body>
</html>
)

PScmd:="""" . "Send-MailMessage -From '" . from . "' -to '" . receiver . "' -Subject '" . subject . "' -BodyAsHtml '" . EmailBody
            . "' -SmtpServer '" . SMTPserver . "' -port '" . SMTPport . "' -UseSsl -Credential (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ('"
            . from . "', (ConvertTo-SecureString -String '" . " %Password% " . "' -AsPlainText -Force)))" . """"
Run,%PSexe% -command %PScmd%,,Hide

User avatar
JoeWinograd
Posts: 2177
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Sending email with CDO.Message using Office 365 SMTP

Post by JoeWinograd » 03 Jun 2021, 11:52

labrint wrote:The trick is to replace -Body with -BodyAsHtml and of course attach the variable
Very nice! Thanks for figuring that out and posting the solution for the rest of us. Regards, Joe

User avatar
labrint
Posts: 379
Joined: 14 Jun 2017, 05:06
Location: Malta

Re: Sending email with CDO.Message using Office 365 SMTP

Post by labrint » 03 Jun 2021, 12:59

JoeWinograd wrote:
03 Jun 2021, 11:52
labrint wrote:The trick is to replace -Body with -BodyAsHtml and of course attach the variable
Very nice! Thanks for figuring that out and posting the solution for the rest of us. Regards, Joe
It pales in comparison with your code. I am very eager if we can move forward on Gmail's security settings. I often attach these SMTP settings to allow clients of mine to use my software to order inventory. Each security feature is a cause of embarrassment when the email fails and it is not a positive experience for the client.

I am mentioning this because probably there are some people here that have the knowledge for such things without their business application. We must keep ahead of these developments to keep our scripts and businesses viable.

User avatar
labrint
Posts: 379
Joined: 14 Jun 2017, 05:06
Location: Malta

Re: Sending email with CDO.Message using Office 365 SMTP

Post by labrint » 11 Jun 2021, 12:57

@JoeWinograd anyway to insert an attachment in your code?

User avatar
JoeWinograd
Posts: 2177
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Sending email with CDO.Message using Office 365 SMTP

Post by JoeWinograd » 11 Jun 2021, 20:11

labrint wrote:anyway to insert an attachment in your code?
Yes. I suggest assigning a file name var at the top of the script, something like this:

Code: Select all

AttachmentFile:="C:\temp\test.txt" ; full path to attached file
Then, in the CDO code, add this statement after the pmsg.TextBody one:

Code: Select all

pmsg.AddAttachment(AttachmentFile)
In the PowerShell code, add this continuation line after the first line of the PScmd assignment statement:

Code: Select all

            . "' -Attachments '" . AttachmentFile
Regards, Joe

User avatar
labrint
Posts: 379
Joined: 14 Jun 2017, 05:06
Location: Malta

Re: Sending email with CDO.Message using Office 365 SMTP

Post by labrint » 12 Jun 2021, 04:19

Works like a charm. Besides that, adding it to a new line makes everything easier to work with. Thanks @JoeWinograd :)
JoeWinograd wrote:
11 Jun 2021, 20:11
labrint wrote:anyway to insert an attachment in your code?
Yes. I suggest assigning a file name var at the top of the script, something like this:

Code: Select all

AttachmentFile:="C:\temp\test.txt" ; full path to attached file
Then, in the CDO code, add this statement after the pmsg.TextBody one:

Code: Select all

pmsg.AddAttachment(AttachmentFile)
In the PowerShell code, add this continuation line after the first line of the PScmd assignment statement:

Code: Select all

            . "' -Attachments '" . AttachmentFile
Regards, Joe

User avatar
JoeWinograd
Posts: 2177
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Sending email with CDO.Message using Office 365 SMTP

Post by JoeWinograd » 12 Jun 2021, 12:06

labrint wrote:Works like a charm.
Glad to hear it!

User avatar
labrint
Posts: 379
Joined: 14 Jun 2017, 05:06
Location: Malta

Re: Sending email with CDO.Message using Office 365 SMTP

Post by labrint » 12 Jul 2021, 10:03

@JoeWinograd Do you know if it is possible to add multiple recipients to this PowerShell email?

User avatar
JoeWinograd
Posts: 2177
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Sending email with CDO.Message using Office 365 SMTP

Post by JoeWinograd » 12 Jul 2021, 11:47

labrint wrote:Do you know if it is possible to add multiple recipients to this PowerShell email?
I've never tried it, but the answer seems to be at the Microsoft doc for Send-MailMessage:
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/send-mailmessage

Example 3 shows how to send to a mailing list. The Parameters section shows how to do a CC and also has this comment on the -To param (copied here under "Fair Use"):

If there are multiple recipients, separate their addresses with a comma (,).

Regards, Joe

S1eepy
Posts: 3
Joined: 06 Oct 2020, 09:24

Re: Sending email with CDO.Message using Office 365 SMTP

Post by S1eepy » 21 Apr 2022, 06:53

Adding multiple attachments is slightly more of a pain - as powershell wants the list of attachments as an array, not a seperated list.

You cant create the array in AHK and pass it to powershell as a variable, you have to create the array in powershell
You can chain powershell commands using a pipe "|" - so creating the array first, then using that array in the Send-MailMessage command worked for me

Code: Select all

AttachmentList := "C:/Att1.txt|C:/Att2.txt|C:/Att3.txt|C:/Att4.txt"

PScmd:="""$AttArray = @('" . StrReplace(AttachmentList, "|" , "','") . "') | Send-MailMessage -From 'sender <[email protected]>' -to '" . ToAddresses . "' -Subject '" . EmailSubject
	 . "' -BodyAsHTML '" . EmailBody . "' -SmtpServer 'smtp.office365.com' -port '587' -UseSsl -Credential (New-Object -TypeName System.Management.Automation.PSCredential "
	 . " -ArgumentList ('[email protected]', (ConvertTo-SecureString -String 'xxx' -AsPlainText -Force)))"""

User avatar
JoeWinograd
Posts: 2177
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Sending email with CDO.Message using Office 365 SMTP

Post by JoeWinograd » 21 Apr 2022, 14:23

S1eepy wrote:using that array in the Send-MailMessage command worked for me
Great stuff! Tested here...worked perfectly! Thanks very much for sharing your solution. Regards, Joe

User avatar
labrint
Posts: 379
Joined: 14 Jun 2017, 05:06
Location: Malta

Re: Sending email with CDO.Message using Office 365 SMTP

Post by labrint » 05 Jul 2022, 07:39

@JoeWinograd @S1eepy Outlook has stopped basic authentication.

https://docs.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/deprecation-of-basic-authentication-exchange-online

Have you figured out how to configure the PowerShell with the new settings?

User avatar
JoeWinograd
Posts: 2177
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Sending email with CDO.Message using Office 365 SMTP

Post by JoeWinograd » 06 Jul 2022, 00:01

labrint wrote:Have you figured out how to configure the PowerShell with the new settings?
For Outlook, the code still works as is with my Outlook.com email, but I don't have access to an Exchange server, so can't help you with that. For Gmail, the code does NOT work as is, ever since Google shut down the "Less secure apps" method on 30-May-2022. To be more precise, the code works, but the password doesn't.

There are several ways to fix it. The one that I chose is to create a so-called App password. Here are the steps:

(1) Set up 2-Step Verification (aka 2FA) in your Google Account (you must do this in order to be able to create App passwords)

(2) Go into App passwords

(3) Select app

(4) Other (Custom name) - give it whatever name you want - I called mine AHKPS

(5) Generate - you'll get a 16-character password

(6) Use that password with the SAME EXACT CODE that I posted above

It will work now! At least, it does here. Regards, Joe

User avatar
JoeWinograd
Posts: 2177
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Sending email with CDO.Message using Office 365 SMTP

Post by JoeWinograd » 16 Jul 2022, 19:10

A quick note to say that you may add Cc and Bcc options to the PowerShell command, such as:

Code: Select all

EmailCc:="[email protected]"
EmailBcc:="[email protected]"
Then the first line of the PowerShell command assignment statement would be:

Code: Select all

PScmd:="""" . "Send-MailMessage -From '" . EmailFrom . "' -To '" . EmailTo . "' -Cc '" . EmailCc . "' -Bcc '" . EmailBcc . "' -Subject '" . EmailSubject . "' -Body '" . EmailBody
Regards, Joe

Post Reply

Return to “Ask for Help (v1)”