Sending Emails with attachments

Started by John Montenigro, April 27, 2014, 07:09:44 PM

Previous topic - Next topic

John Montenigro

A few years ago, I was able to convert a native PB emailer to FF, but it didn't handle attachments. I hit many snags as I tried to upgrade the code, so I decided to look for samples of code that already handled attachments.

I scoured the PB forum, this forum, and the Jose Roca forum for information. I found many examples and fragments, and tried (unsuccessfully) to get them to compile.

So then I figured: let me go straight to the routines that I know are in Jose's headers: CAfxSmtpMail.inc

That file looks like CLASS stuff that I've never used, so I'm a bit hesitant. I do see that the end of the file contains a native PBMAIN, so I'm converting that over to fit into my FF code.

I'm most curious about these lines:
   cMail.AuthType     = "AUTH LOGIN"
   cMail.AuthUsername = "myusername@something.com"
   cMail.AuthPassword = "mypassword"

In the simple code I used to use, I never had to enter any authorization info. Do I REALLY have to put my password into a string? REALLY? It would be visible if I examined the EXE in a hex editor, so that can't be right!

And I have no clue what AuthType is, or what values it would take. Where can I read about that?

I appreciate any and all help offered!!

Thanks,
-John





David Kenny

John,

I think the "AUTH CRAM-MD5" is more secure than the other two.
The AuthPassword can come from any "string source".  In FF, for instance: cMail.AuthPassword = FF_Control_GetText(HWND_LogInFrm_PassWTb)

David

John Montenigro

Thanks, David,

Please forgive my ignorance -- what other two? 

I've been trying to get any intelligent info from MSDN and have nothing.

But I don't understand why my old code sends email, but this new class thing fails to connect! Since that's an early test in the SendMail method, I'm inclined to think that one of the new properties or attributes is set wrong, that wasn't being set in the old code...  but I can't tell which.

Can you point me to any documentation that I could read/study?

Thanks,
-John


David Kenny

Sorry John,

I've been away for over a day.
Quotewhat other two?
There are three AuthType's documented in Jose's "Windows API Wrappers Reference".
AUTH LOGIN
AUTH PLAIN
AUTH CRAM-MD5

Here is a site that had some detailed information on the three: http://www.samlogic.net/articles/smtp-commands-reference-auth.htm

QuoteI've been trying to get any intelligent info from MSDN and have nothing.
It has to do with SMTP.  SMTP is a internet mail protocol, you can implement it in any language and access it with any language. But MS didn't create it, so they wouldn't document it. 

QuoteCan you point me to any documentation that I could read/study?
The following example code is from Jose's help file mentioned above:
' ===========================================================================================
' Usage example.
' ===========================================================================================
#COMPILE EXE
#INCLUDE "CAfxSmtpMail.inc"

FUNCTION PBMAIN () AS LONG

' NOTES:
' The 'SendTo', 'CC', 'BCC' fields can be a one address or a
' semicolon(;) or comma(,) deliminated list of multiple addresses.
' SMTP only allows 100 recipients max at a time (per rfc821), therefore
' for large mailings you should break it into multiple emails.

' Multiple attachments can be sent by simply separating the file
' names with a semicolon or comma.

' You can use 'Plain' text emails or 'HTML' emails, or 'Both'.
' When sending "Both", the email client application will use whichever
' one it can render based on the user's settings.

' Default values for the following that are already set by the
' class (constructor). Change them here if you want a different value.
' e.g.
' cMail.ServerTimeOut = 60000  ' milliseconds  ' default is 60000
' cMail.LocalHost     = "MySuperComputer"      ' default is localhost
' cMail.CharSet       = "us-ascii"             ' default is iso-8859-1
' cMail.MessageStyle  = "both"                 ' default is Plain

LOCAL cMail AS AfxSmtpMail
cMail = CLASS "CAfxSmtpMail"

cMail.SMTPServer   = "mysmtpxxxx.com"
cMail.SendFrom     = "support@planetsquires.com"
cMail.SendTo       = "support@planetsquires.com"
cMail.CC           = "support@planetsquires.com"
cMail.BCC          = "planetsquires@gmail.com"
cMail.ReplyTo      = "support@planetsquires.com"
cMail.Subject      = "test subject"

cMail.EnableAuth   = %TRUE
cMail.AuthType     = "AUTH LOGIN"
cMail.AuthUsername = "myusername@something.com"
cMail.AuthPassword = "mypassword"

cMail.MessageStyle = "both"
cMail.Attachments  = ""       ' eg. "myfilename.zip"

' // HTML text email
cMail.HTMLMessage  = "<html>" & $CRLF  & _
                      "<body>" & $CRLF  & _
                      "<center><b>This Is a test!</b></center>" & $CRLF & _
                      "</body>" & $CRLF & _
                      "</html>" & $CRLF

' // Send the actual email and deal with any error/message response.
IF ISFALSE cMail.SendMail THEN
    MSGBOX "Error sending email:  " & cMail.Response
ELSE
    MSGBOX "Email(s) sent okay."
END IF

END FUNCTION
' ===========================================================================================

I had assumed that you had already seen this and is where you got your example code from.  It appears to be a complete example but I have not tested it.  I would start there.  You might also check Jose's site.  He is really good about posting examples of most things his wrappers cover.  Sometimes it is challenging to find them though.  You can post questions there also (you need to have a login and that means sending a request to Jose himself).

Another avenue would be to ask Paul (Squires of course). Jose's mail class is heavily based off the work of Paul (posted on PB's website).  Paul's code brought good comments from other forum members who tried it.

BTW, I tried Paul's code from PB.com and Jose's both.  They didn't work for me either.  I thought, since I use GMail, that it would be as simple as setting the SMTPPort property because GMail uses a non-standard port. It was a step in the right direction because it changed the error message from "Error sending email: Cannot connect to E-mail server: SMTP.gmail.com" to "Error sending email:". Normally, for GMail, you also have to tell your email client to use SSL, but I couldn't find any settings for that.  I didn't attempt to trouble shoot it any further.

David

Richard Kelly

Grab some source code I posted on the PB forums in April 2010. It's doesn't do secure sockets and it was one of my early attempts so be nice to me.


http://www.powerbasic.com/support/pbforums/showthread.php?t=43403


Rick

José Roca

As stated in the header of CAfxSmtpMail.inc:

Quote
' Based on code posted by Paul Squires at:
' http://www.powerbasic.com/support/pbforums/showthread.php?t=41961&highlight=tcp
' with minimal changes by Jose Roca (also changed the logic of the return value of the
' SendMail method)

I only did some small changes to avoid possible conflicts with my headers.

David Kenny

Jose, I saw your acknowledgment in the header.  I should have quoted it like you did. It was not my intention to imply that it was not properly acknowledged.  If it did come across that way, please accept my profuse apology.

Rick, I wish I could say it is definitely SSL that is causing my problem with GMail.  But I am far from being able to claim that with certainty.  I'm just stating that it's the only thing I could see right off that might be a problem.  As I stated, when setting up MS Outlook (or other email clients), I have to make sure SSL is checked or it just wont work.  I will give yours a try. Thanks for the link.

John,  I appeared to have contradicted myself in my last post about trying the code referenced.  I hadn't when I wrote that, but I had some things to do, and didn't finish the post until the next day.  I had tested the class before I finished the post as documented in the "BTW" at the bottom.

All, again I stopped here and tried some other things.  I tried a yahoo email account of mine.  Just as GMail, it uses SSL and outgoing port 465.  It failed the same as GMail.  I then tried my wife's email through our local ISP.  It doesn't require SSL and uses the default port of 25.  It works.  I know others at PB's forums had luck with setting the port with the SMTPPort method, so I am still thinking that it is the SSL requirement that is the problem.  Also, BTW, the attachment came through fine!

David

José Roca

This works with gmail:


#COMPILE EXE
#DIM ALL
#INCLUDE ONCE "windows.inc"
#INCLUDE ONCE "cdosys.inc"
#INCLUDE ONCE "ado.inc"
#INCLUDE ONCE "ole2utils.inc"

FUNCTION PBMAIN () AS LONG

   DIM iMsg AS CDO_IMessage
   DIM iConf AS CDO_IConfiguration
   DIM Flds AS ADOFields

   iMsg = NEWCOM "CDO.Message"
   iConf = NEWCOM "CDO.Configuration"

   TRY

      Flds = iConf.Fields
      DIM schema AS STRING
      schema = "http://schemas.microsoft.com/cdo/configuration/"
      Flds.Item(schema & "sendusing").Value = 2
      Flds.Item(schema & "smtpserver").Value = "smtp.gmail.com"
      Flds.Item(schema & "smtpserverport").Value = 465
      Flds.Item(schema & "smtpauthenticate").Value = 1
      Flds.Item(schema & "sendusername").Value = "mymail@gmail.com"
      Flds.Item(schema & "sendpassword").Value =  "mypassword"
      Flds.Item(schema & "smtpusessl").Value = 1
      Flds.Update

      iMsg.To = "your first email address"
      iMsg.From = "your 2nd email address"
      iMsg.Subject = "Test send with gmail account"
      iMsg.HTMLBody = "Test send with gmail account"
      iMsg.Sender = "your name"
      iMsg.Organization = "Jose Roca"
      iMsg.ReplyTo = "your 2nd email address"
      iMsg.Configuration = iConf
      iMsg.Send
      ? "Message sent successfully"
   CATCH
      ? OleGetErrorInfo(OBJRESULT)
   END TRY

END FUNCTION


John Montenigro

Thanks for the help, guys!

Richard,
Your code was among many SMTP threads I looked at over the past week, and I downloaded the ZIP, but haven't started to experiment with it yet. I promise I will, and I promise I will be nice, too! Thanks!

David,
Thanks for letting me know that SMTP is not MS, so I'll search farther across the net for more info...

Yes, I did use the example code at the end of Jose's CAfxSmtpMail.inc. But I hadn't examined the file enough to recognize the MD5 type you mentioned. So between messages, I went back and examined CAfxSmtpMail.inc more closely, found the 3 types, and have been experimenting with them (and lots of other settings...)

Jose,
I saw Paul's code too, but I stopped trying to get into it when I saw your note that your code is based on his. My first presumption was that your code covered his completely. Now, I wonder if that's an incorrect assumption on my part. Because I'm only programming occasionally, I find it really hard to decipher the threads on all the different forums where there are "code mazes" and ambiguities. I apologize, I'm one that has to start with a complete example; it's really hard for me to keep up with the professionals who can grab snippets and fragments and produce a grand masterpiece!

If you could just let me know if there is more to Paul's code than your code covers that I should be trying to incorporate, I'll go back and re-examine it. I am more than willing to read and experiment and learn, so I'm appreciative if you can just tell me where I should be looking.

I see a newer post with GMAIL settings. I will experiment with them, too.

ALL:
I think I may also be experiencing a firewall problem at home:
- I had no success all weekend trying to send emails from my laptop using code based on CAfxSmtpMail.inc.
- This morning at work, code that I had compiled at home over the weekend DID succeed in getting a message out! I had made no changes and had not re-compiled...

SO, I will continue experimenting and reporting back. I thank you all for your ideas and suggestions!
-John

P.S. I have 3 email accounts, and I generally test each EXE against:
- Comcast.net
- gmail.com
- businesss.com

Now, I'm thinking there are very different settings for each that I have to re-organize.

Does it matter that the LAN at work is running Outlook? (I have never been able to send a message through that account.)



John Montenigro

Quote from: Jose Roca on April 29, 2014, 02:50:20 PM
This works with gmail:


#COMPILE EXE
#DIM ALL
#INCLUDE ONCE "windows.inc"
#INCLUDE ONCE "cdosys.inc"
#INCLUDE ONCE "ado.inc"
#INCLUDE ONCE "ole2utils.inc"

FUNCTION PBMAIN () AS LONG

   DIM iMsg AS CDO_IMessage
   DIM iConf AS CDO_IConfiguration
   DIM Flds AS ADOFields

   iMsg = NEWCOM "CDO.Message"
   iConf = NEWCOM "CDO.Configuration"

   TRY

      Flds = iConf.Fields
      DIM schema AS STRING
      schema = "http://schemas.microsoft.com/cdo/configuration/"
      Flds.Item(schema & "sendusing").Value = 2
      Flds.Item(schema & "smtpserver").Value = "smtp.gmail.com"
      Flds.Item(schema & "smtpserverport").Value = 465
      Flds.Item(schema & "smtpauthenticate").Value = 1
      Flds.Item(schema & "sendusername").Value = "mymail@gmail.com"
      Flds.Item(schema & "sendpassword").Value =  "mypassword"
      Flds.Item(schema & "smtpusessl").Value = 1
      Flds.Update

      iMsg.To = "your first email address"
      iMsg.From = "your 2nd email address"
      iMsg.Subject = "Test send with gmail account"
      iMsg.HTMLBody = "Test send with gmail account"
      iMsg.Sender = "your name"
      iMsg.Organization = "Jose Roca"
      iMsg.ReplyTo = "your 2nd email address"
      iMsg.Configuration = iConf
      iMsg.Send
      ? "Message sent successfully"
   CATCH
      ? OleGetErrorInfo(OBJRESULT)
   END TRY

END FUNCTION


Jose,
Am I understanding correctly that CAfxSmtpMail.inc does not handle GMAIL accounts? That in order to handle GMAIL, I must use those additional include files, and this ADO/schema?

Not that it would be difficult to incorporate, but just wondering because it's not mentioned anywhere else that this is the proper/only approach...

Thanks,
-John

John Montenigro

David,
Quotea site that had some detailed information on the three: http://www.samlogic.net/articles/smtp-commands-reference-auth.htm

This is great! Thank you for this link!!!

OK, I'm off and reading for awhile!
-John

José Roca

#11
>Am I understanding correctly that CAfxSmtpMail.inc does not handle GMAIL accounts?
> That in order to handle GMAIL, I must use those additional include files, and this ADO/schema?

That class from Paul uses obsolete PowerBASIC's TCP statements. I never use them. I just incorporated his class into my headers because so many people wants to use no matter what except COM (Component Object Model), specially if it uses PB built-in statements.

The requirements have changed, but PB's TCP statements don't. M$ added a configuration schema for security reasons.

The following example, sends an email with an attachment using an smtp server.


' ########################################################################################
' CDO - Sending a text email with an attached file.
' ########################################################################################

' SED_PBWIN - Use the PBWin compiler
#COMPILE EXE
#DIM ALL
#INCLUDE ONCE "CDOSYS.INC"
#INCLUDE ONCE "OLE2UTILS.INC"

' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN () AS LONG

   LOCAL pMessage AS CDO_IMessage   ' // CDOSYS - IMessage interface
   LOCAL iConf AS CDO_IConfiguration
   LOCAL Flds AS ADOFields

   ' // Create an instance of the CDO Message interface
   pMessage = NEWCOM("CDO.Message")
   IF ISNOTHING(pMessage) THEN EXIT FUNCTION
   iConf = NEWCOM "CDO.Configuration"
   IF ISNOTHING(iConf) THEN EXIT FUNCTION

   TRY
      ' // Configuration
      Flds = iConf.Fields
      LOCAL schema AS STRING
      schema = "http://schemas.microsoft.com/cdo/configuration/"
      Flds.Item(schema & "sendusing").Value = %CdoSendUsingPort
      Flds.Item(schema & "smtpserver").Value = "<your smtp server name>"  ' --> change me
      Flds.Item(schema & "smtpserverport").Value = 25
      Flds.Item(schema & "smtpauthenticate").Value = 1
      Flds.Item(schema & "sendusername").Value = <"your email address">  ' --> change me
      Flds.Item(schema & "sendpassword").Value =  "<your password>"  ' --> change me
      Flds.Item(schema & "smtpusessl").Value = 1
      Flds.Update
      ' // Recipient name --> change as needed
      pMessage.To = "<recipient address>"  ' --> change me
      ' // Sender name --> change as needed
      pMessage.From = "<your email address>"  ' --> change me
      ' // Subject --> change as needed
      pMessage.Subject = "This is a sample subject"
      ' // Text body --> change as needed
      pMessage.TextBody = "This is a sample message text"
      ' // Add the attachment (use absolute paths).
      ' // Note  By repeating the call you can attach more than one file.
      pMessage.AddAttachment "<absolute path of the attachement>"  ' --> change me
      ' // Set the configuration
      pMessage.Configuration = iConf
      ' // Send the message
      pMessage.Send
      MSGBOX "Message sent"
   CATCH
      ' // Display the error message
      OleShowErrorInfo OBJRESULT
   FINALLY
      ' // Release the Message object
      pMessage = NOTHING
   END TRY

END FUNCTION
' ========================================================================================


Warning: The web is full of obsolete CDO scripts that don't use the configuration schema and won't work with Windows 7.

José Roca

#12
MSDN information about "http://schemas.microsoft.com/cdo/configuration/"

Link: http://msdn.microsoft.com/en-us/library/ms526318%28v=exchg.10%29.aspx

PS: Don't take the above example literally. It all depends of your configuration. Fields like "smtpauthenticate" must be filled if your server requires authentication; otherwise, don't.

An added value of using CDO is that if there is an error, my function OleShowErrorInfo OBJRESULT will display an, hopefully, meaningful message.

José Roca

Quote
Jose,
Am I understanding correctly that CAfxSmtpMail.inc does not handle GMAIL accounts? That in order to handle GMAIL, I must use those additional include files, and this ADO/schema?

Not that it would be difficult to incorporate, but just wondering because it's not mentioned anywhere else that this is the proper/only approach...

I don't know if there are other ways (probably, yes), but this is the one that works for me.

John Montenigro

Thanks, Jose!

After a bit of tweaking, I was able to send a message with attachment from a POP3 account at the office!!! Hooray!!!

I'll see what happens tonight at home...

Next, I'm going to try sending via GMAIL account and then from an Exchange account...

I'll be back!

Thanks again,
-John