Sending massive mails

  1. ‹ Older
  2. 2 months ago

    Christian S

    Jun 17 Pre-Release Testers, Xojo Pro, XDC Speakers Germany

    Please review MassEmailer example coming with MBS Xojo CURL Plugin .
    it sends a thousand emails easily and delays them optionally to start an email every 5 seconds only to add some delay.

  3. Michel B

    Jun 17 Pre-Release Testers, Xojo Pro RubberViews.com

    Ciro, why reinvent the wheel ?

    Sending mass email is much easily done with a specialized service, such as mailchimp.com , which will not only send mail without risk for your email account, but also manage unsubscribe.

  4. Scott C

    Jun 17 Pre-Release Testers, Xojo Pro Vancouver, Canada
    Edited 2 months ago

    Sending mass emails is certainly an ongoing problem. And not that I'm trying to change the topic away from this important discussion, or discourage anyone from using Xojo as their solution tool.

    But I hope it might be helpful to point out that Microsoft SQL Server (which @Ciro M appears to be using) has it's own send mail functions, a.k.a., Database Mail .

    The key benefits are:

    • A configurable retry queue, like a real SMTP server
    • Very reliable (I've been using this feature for years, although not for marketing purposes)
    • Logging tables to report the success or failure of each email send attempt
    • Features to resend previously undeliverable email.

    See The sp_send_dbmail Procedure and Check the Status of Emails sent with Database Mail

    You may have to get your hands dirty with writing a couple of Stored Procedures to manage this (many examples can be found by googling), but then I think you can call the Procedures from Xojo or even put the Send on a schedule using SQL Jobs.

    I hope that helps.

    Edited: To add extra link

  5. Tomas J

    Jun 17 Pre-Release Testers, Xojo Pro Europe (Germany)
    Edited 2 months ago

    I advice to use your own smtp email server as mail gateway or proxy to the ISP. At least this would put you in a comfort position to debug this issue and to check the sent email.

    While auditing the code: It's nice to see how easily any malformed recordset could break in and execute SQL commands and gain access to your system (in context of SA if used!) No prepared statements or stored procedures not even a sanitation or encoding of your DB Strings. This could also lead your ISP to drop your emails due malformed strings. If your data comes from a web interface with the same missing sanitation then you will come into different problems soon. Try to enforce Privacy and Security by Default. This code is not really nice.

  6. Michel B

    Jun 17 Pre-Release Testers, Xojo Pro RubberViews.com

    Be very careful using your precious professional email server to debug, or to send mass email. ISPs are extremely touchy with spam in all forms, and a handful of complaints from recipients about unsolicited email may prompt them to deactivate your account.

    Better get a specialized service that knows how to handle that kind of activity, such as mailgun.com.

    May I also stress how important it is to manage unsubscribes. Especially in Europe with GDPR.

  7. Tomas J

    Jun 18 Pre-Release Testers, Xojo Pro Europe (Germany)
    Edited 2 months ago

    Hello Michel, yes thank you for clarifying this issue with ISP mail servers. This is the reason why to use your own mailserver as gateway or proxy, so you can debug and of course contol (and prevent while developing) mass mailings. Though the 150 mails in question are far from being considered as "mass" in many cases.

    Talking about GDPR. You will need a good argument to justify this step as there are better ways without the need to transfer data to any third party. Otherwise you would violate a couple of recitals. But I am afraid we are going offtopic. Let's open a new thread if you want to discuss this further.

  8. Michel B

    Jun 18 Pre-Release Testers, Xojo Pro RubberViews.com
    Edited 2 months ago

    Tomas, I did not intend to discuss GDPR per se, but the general risks involved in sending out potentially unsolicited mail. This was directed at the OP.

  9. 3 weeks ago

    hello! thanks for the answers, lately I decided to use an external smtp, it is called mailgun.

    the problem now is that:

    if I sent a mail in the action event of a button, like this:

    dim Socket1 as new SMTPSecureSocket
    Dim mail As EmailMessage
    
    // set up the socket
    Socket1.Address = "smtp.eu.mailgun.org"
    Socket1.Port = 587
    
    Socket1.UserName = "myuser@mailgun......"
    Socket1.Password = "mypassword......"
    
    // populate the email message
    mail = New EmailMessage
    mail.FromAddress = "myuser@mailgun......"
    mail.AddRecipient("emmecisistemi@gmail.com")
    
    mail.Subject = "prova mailgun"
    mail.BodyPlainText = "test invio mail!"
    'mail.Headers.AppendHeader("X-Mailer","SMTP Test")
    
    // send the email
    Socket1.Messages.Append(mail)
    Socket1.SendMail
    
    MsgBox("mail inviata")

    works like a charm! But, If I use a timer object trying to send automatically 1 email every 5 minutes like this:

    Dim d As New Date
    Dim commessa,stato,stringa_data as string
    Dim destinatario,soggetto,testocom as string
    stringa_data=d.Year.ToText
    stringa_data=Mid(stringa_data,3,2)
    
    if d.Month < 10 then
      stringa_data=stringa_data+"0"+d.Month.ToText
    else
      stringa_data=stringa_data+d.Month.ToText
    end if
    if d.Day < 10 then
      stringa_data=stringa_data+"0"+d.Day.ToText
    else
      stringa_data=stringa_data+d.Day.ToText
    end if
    if d.Hour < 10 then
      stringa_data=stringa_data+"0"+d.Hour.ToText
    else
      stringa_data=stringa_data+d.Hour.ToText
    end if
    if d.Minute < 10 then
      stringa_data=stringa_data+"0"+d.Minute.ToText
    else
      stringa_data=stringa_data+d.Minute.ToText
    end if
    
    Dim db As New MSSQLServerDatabase
    
    db.Host ="192.1.1.1" // or just the IP if using the default instance
    db.DatabaseName = "SalCommessa"
    db.UserName = "sa"  // or "Domain\UserID for trusted domain accounts
    db.Password = "xxx"
    
    If db.Connect Then
      //recupero commesse
      dim stringa_sql as string
      Dim ps As MSSQLServerPreparedStatement
      Dim ps2 As MSSQLServerPreparedStatement
      Dim rs As RecordSet 
      //invio mail solo se per questo stato non esiste già 
      stringa_sql="Select top 1 Elenco_Commesse.Commessa,Elenco_Commesse.Codice_Cliente,Elenco_Commesse.Ragione_Sociale,"
      stringa_sql=stringa_sql+"Elenco_Commesse.E_Mail,Elenco_Commesse.Italia_Estero,Elenco_Commesse.Perc_Lavorato,"
      stringa_sql=stringa_sql+"Elenco_Commesse.Stato,Elenco_Commesse.Data_Consegna,isnull(Log_Invio.Data_Invio,'NO') as Data_Invio,"
      stringa_sql=stringa_sql+"Parametri_Invio.Destinatari_EMail_Ita,Parametri_Invio.Destinatari_EMail_Est,"
      stringa_sql=stringa_sql+"Parametri_Invio.Oggetto_EMail,Parametri_Invio.Testo_EMail"
      stringa_sql=stringa_sql+" from Elenco_Commesse "
      stringa_sql=stringa_sql+" left outer join Log_Invio on Elenco_Commesse.Commessa=Log_Invio.Commessa and "
      stringa_sql=stringa_sql+" Elenco_Commesse.Stato=Log_Invio.Stato "
      stringa_sql=stringa_sql+" left outer join Parametri_Invio on Elenco_Commesse.Stato=Parametri_Invio.Stato "
      stringa_sql=stringa_sql+" where Log_Invio.Data_Invio is null"
      stringa_sql=stringa_sql+" order by Commessa "
      ps = db.Prepare(stringa_sql)
      rs = ps.SQLSelect
      
      if rs <> Nil Then
        While Not rs.EOF
          commessa=rs.IdxField(1).StringValue
          stato=rs.IdxField(7).StringValue
          destinatario="emmecisistemi@gmail.com"
          soggetto=rs.IdxField(12).StringValue
          testocom = ""
          testocom=testocom+rs.IdxField(13).StringValue
          rs.MoveNext
        Wend
        rs.Close
      else
        commessa="NO"
      end if
      
      
      if commessa <> "NO" then
        dim Socket1 as new SMTPSecureSocket
        Dim mail As EmailMessage
        
        // set up the socket
        Socket1.Address = "smtp.eu.mailgun.org"
        Socket1.Port = 587
        
    Socket1.UserName = "myuser@mailgun......"
    Socket1.Password = "mypassword......"
        
        // populate the email message
        mail = New EmailMessage
        mail.FromAddress = "myuser@mailgun......"
        mail.AddRecipient("emmecisistemi@gmail.com")
        
        mail.Subject = "prova mailgun"
        mail.BodyPlainText = "test invio mail!"
        'mail.Headers.AppendHeader("X-Mailer","SMTP Test")
        
        // send the email
        Socket1.Messages.Append(mail)
        Socket1.SendMail
        
        '//aggiorniamo il log
        stringa_sql="INSERT INTO Log_Invio (Commessa,Stato,Data_Invio)"
        stringa_sql=stringa_sql+"VALUES "
        stringa_sql=stringa_sql+"('"+commessa+"',"
        stringa_sql=stringa_sql+"'"+stato+"',"
        stringa_sql=stringa_sql+"'"+stringa_data+"')"
        ps2 = db.Prepare(stringa_sql)
        ps2.SQLExecute
        
        break
      end if
      
      db.Close
    Else
      MsgBox("Connection error:" + db.ErrorMessage)
    End If

    no mail is sent...... any idea? maybe a timer problem?

    regards,

  10. Christian S

    Jul 30 Pre-Release Testers, Xojo Pro, XDC Speakers Germany

    SendMail is asynchonously. You need to wait till it is done and MailSent event fires.

    Otherwise you kill the socket at end of block.

  11. Christian S

    Jul 30 Pre-Release Testers, Xojo Pro, XDC Speakers Germany

    Also check email sender example coming with MBS Xojo Plugins :

    https://monkeybreadsoftware.net/example-curl-sendemail-massemailer.shtml

  12. christian, can I use your CURL plugin ?

  13. Christian S

    Jul 31 Pre-Release Testers, Xojo Pro, XDC Speakers Germany

    Your license is old and you may want to get a new one (or Complete Set)

  14. @ChristianSchmitz SendMail is asynchonously. You need to wait till it is done and MailSent event fires.

    Otherwise you kill the socket at end of block.

    tried with socket1.close but doesn't work

  15. Christian S

    Aug 1 Pre-Release Testers, Xojo Pro, XDC Speakers Germany

    Why did you try close?
    The problem is that you don't wait for SendMail to finish.

  16. 2 weeks ago

    You may be running into hosting issues. Even if you aren’t, there is a Massive chance that your emails are either going to be blocked by your host after they are pushed through the server or flagged by the recipient’s host. Might I suggest MailChimp for marketing emails?

    However, if you MUST push emails in bulk through an app, I would do it one by one with some space between them. Nothing shouts “bulk email/spam” like 20+ emails leaving the same account within milliseconds of each other.

    Just my 2 cents...

  17. Christian S

    Aug 5 Pre-Release Testers, Xojo Pro, XDC Speakers Germany
    Edited 2 weeks ago

    With our mail provider I had to contact their tech support to raise the limit of 250 emails per hour for my sending email account.
    Then I can send thousands in a batch easily.

  18. Edited 2 weeks ago

    so, let me clarify.....

    to avoid being blocked by Isp I'm using an account of a professional SMTP service (MailGun) that will do the job.

    If I send one mail only (for example in the action event of a button) everything is fine.
    But, I'm using a recordset and a timer, every 5 minutes I take the first record (top1) from the recordset and send the mail, then I remove it from the recordset. The query is working because I've had a log feature.

    this way no email is received!

  19. Sascha S

    Aug 7 Pre-Release Testers, Xojo Pro Germany, Lower Saxonary

    @Ciro M to avoid being blocked by Isp I'm using an account of a professional SMTP service (MailGun) that will do the job.

    But then you could even use their Batch Send Features .

    On another note: I'd reccomend to create a "MailGun Class" and use it as a property for your Window or App f.e. This will make it harder to get out of scope before it finished it's work and i think you could make your Code much more easier to maintain. ;)

  20. Sascha S

    Aug 7 Pre-Release Testers, Xojo Pro Germany, Lower Saxonary

    @Ciro M But, I'm using a recordset and a timer, every 5 minutes I take the first record (top1) from the recordset and send the mail, then I remove it from the recordset. The query is working because I've had a log feature.

    But are you sure the connection does not drop while you are pausing for 5 minutes and that the RecordSet is still in scope/available?

  21. Sascha S

    Aug 7 Pre-Release Testers, Xojo Pro Germany, Lower Saxonary

    You write:

    @Ciro M works like a charm! But, If I use a timer object trying to send automatically 1 email every 5 minutes like this:

    And then in your example you "move" through all the recordsets and then close the RecordSet.

    @Ciro M if rs <> Nil Then
    While Not rs.EOF
    commessa=rs.IdxField(1).StringValue
    stato=rs.IdxField(7).StringValue
    destinatario="emmecisistemi@gmail.com"
    soggetto=rs.IdxField(12).StringValue
    testocom = ""
    testocom=testocom+rs.IdxField(13).StringValue
    rs.MoveNext
    Wend
    rs.Close
    else
    commessa="NO"
    end if

    Would'nt this just send the last Record from the Set? Because you would start over again each Timer run? (But i do not understand italian language and did not check the querry...)
    As an alternative you could make the RecordSet a Property of your Window and call it ONCE. then use your 5 minutes Timer to pull a Set from the Records, move to the next, wait 5 minutes and then repeat.

    And, why do you use a PreparedStatement? If i am right, you do not add user input to your querry, so ther's no need for a prepared statement. Not "wrong" per se, but... ;)

or Sign Up to reply!