B4J Question SMTP2GO for sending email

AKJammer

Active Member
Licensed User
Does anyone have any experience with sending email through SMTP2GO? I'm learning to use JSON at the same time as trying to get an email feature added to an application.

Stripped down, this is what I've got now.

SMTPSendx:
Sub sendSMTPx (pid As Int, msgType As String, fname As String, toEmail As String, ticket As String)
    
    Dim jsonReturn As JSONParser
    Dim jsonGen As JSONGenerator
    
    Dim map1 As Map
    Dim map2 As Map
    Dim m As Map
    Dim toLst As List
    Dim datamap As Map
    
    
    Dim event As String = "Dance Event"
    Dim templateID As String = SMTPTemplateVIP ' "3233442"
    Dim subject As String = "Registration"
    Dim templateMap As Map =  CreateMap("first_name":fname,"event_name":event,"ticket_type":ticket)
    Dim status As String
    Dim SenderSMTP As String = SMTPSender '"mysend@mydomain.com"
    Dim apiKey As String = SMTPapi '"api-47478934973289472879238" ( No, not the real key :-)  )
    Dim SMTP2GO As String = "https://api.smtp2go.com/v3/email/send"

    toLst.Initialize
    datamap.initialize   
    map2.initialize
    
    toLst.Add(toEmail)
                
    map1= CreateMap("sender":SenderSMTP, "to":toLst, "subject":subject, "template_id":templateID, "template_data": templateMap)
    jsonGen.Initialize(map1)   
    
    Log(jsonGen.ToPrettyString(3))           

    Dim j As HttpJob
    j.Initialize("", Me)
    j.poststring(SMTP2GO,jsonGen)
    j.GetRequest.SetHeader("Content-Type", "application/json")
    j.GetRequest.SetHeader("X-Smtp2go-Api-Key", apiKey)

    Wait For (j) JobDone(j As HttpJob)
        
    jsonReturn.Initialize(J.GetString)
    map2 = jsonReturn.NextObject
    datamap = map2.Get("data")
    status = datamap.Get("succeeded")

    j.Release
End Sub

The JSON that it's sending is:
{
"template_data": {
"ticket_type": "VIP Comp (Staff)",
"event_name": "Dance Event",
"first_name": "James (Jim)"
},
"sender": "mysend@mydomain.com",
"subject": "Registration",
"template_id": "3233442",
"to": [
"Jim@MyDomain.com"
]
}

But I keep getting this response.

Response:
ResponseError. Reason: Bad Request, Response: {"request_id": "33059300-d108-11ef-8c06-f23c92160e3c", 
                                                        "data": {"error": "An error occurred processing the json data you sent with the request. 
                                                                    Please make sure the data conforms to the specification for this call 
                                                                    (see the documentation here: https://developers.smtp2go.com/reference/introduction-1)
                                                                    and try again. Don't forget to set Content-Type to 'application/json'.", 
                                                                 "error_code": "E_ApiResponseCodes.NON_VALIDATING_IN_PAYLOAD", 
                                                                 "model_validation_errors": "Model Validation failed: 
                                                                            Either 'text_body', 'html_body' or 'template_id' must be passed"}}
The model validation error says I have to pass "template_id", but it's there in the JSON.

The order of the JSON isn't supposed to matter, it it?

Any assistance is appreciated,
Thanks,
Jim
 

EnriqueGonzalez

Expert
Licensed User
Longtime User
Trying to find something different from those on the documents. it says:
1736710308143.png


that it should be formatted as name <mail@example.com>
may be you are missing the name part.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
j.GetRequest.SetHeader("Content-Type", "application/json") is wrong. okhttp has its own special contenttype header.
it's:
j.GetRequest.SetContentType("application/json")
 
Upvote 0

AKJammer

Active Member
Licensed User
Mail format is ok. It's the same format I use when I go through their test example.

I changed application header set statement to
j.GetRequest.SetContentType("application/json")

Ran it again and it gave this error:

ResponseError. Reason: Bad Request, Response:
{"request_id": "7855d980-d124-11ef-ba60-f23c9216bf47",
"data": {"error": "Failed to parse json payload: error Expecting value: line 1 column 1 (char 0)", "error_code": "E_ApiResponseCodes.INVALID_IN_PAYLOAD"}}
 
Upvote 0

tchart

Well-Known Member
Licensed User
Longtime User
Why not just use their SMTP relay? Been using this for several years

B4X:
Sub SendEmail(email As String, subject As String, message As String)
    Dim smtp As SMTP
    smtp.Initialize("mail.smtp2go.com",465,"noreply@abc.com","PASSWORD","mail")
        
    smtp.UseSSL = True   
    smtp.MailFrom = "noreply@abc.com"
    smtp.Subject = subject
    
    If email.Contains(";") Then
        Dim emails() As String = Regex.split(";",email)
                
        For Each address As String In emails
            smtp.To.Add(address)
        Next
    Else
        smtp.To.Add(email)
    End If   
    
    smtp.Body = message   
    smtp.Send
End Sub
 
Upvote 0

AKJammer

Active Member
Licensed User
@tchart, No particular reason. Was thinking API would be easier. Will give your code a go.


Ah, Now I remember. Straight SMTP doesn't allow the use of their templates. I'd have to build the messages on the fly. Will use as a last resort if I can't get the API working. Thanks.
 
Last edited:
Upvote 0

tchart

Well-Known Member
Licensed User
Longtime User
Oh I see you are using templates. I don’t know if you can use those with the SMTP library. I’ll have a play with those.
 
Upvote 0

AKJammer

Active Member
Licensed User
Ok, so I've gotten this solved, but not on my own.

Grok is XAI's new LLM AI. It was only available to subscribed X (twitter) users, so I've never used it before. But they just released it as a separate free app that can be downloaded. So I did and asked it this:

Code a subroutine in B4J that sends an email using smtp2go api.

This is what it gave me:

Grok generated code:
Sub SendEmailWithSMTP2GO(Recipient As String, Subject As String, Body As String)
    Dim Job As HttpJob
    Job.Initialize("SMTP2GO", Me)

    ' Prepare the JSON payload
    Dim json As JSONGenerator
    json.Initialize(CreateMap(
        "api_key": "YOUR_API_KEY_HERE", ' Replace with your actual API key
        "to": Array(Recipient),
        "sender": "SenderName <sender@example.com>", ' Replace with your verified sender email
        "subject": Subject,
        "text_body": Body
    ))

    ' Set up the HTTP request
    Job.PostString("https://api.smtp2go.com/v3/email/send", json.ToString)
    Job.GetRequest.SetHeader("Content-Type", "application/json")
    Job.GetRequest.SetHeader("X-Smtp2go-Api-Key", "YOUR_API_KEY_HERE") ' Replace with your actual API key

    ' Wait for the response
    Wait For (Job) JobDone(job As HttpJob)
    If Job.Success Then
        Log("Email sent successfully: " & Job.GetString)
    Else
        Log("Error sending email: " & Job.ErrorMessage)
    End If
    Job.Release
End Sub

' Example usage of the subroutine in a B4J module:
Sub Button1_Click
    SendEmailWithSMTP2GO("recipient@example.com", "Test Subject", "This is a test email body.")
End Sub
```

**Important Notes:**
- Replace `"YOUR_API_KEY_HERE"` with your actual SMTP2GO API key.
- Replace `"SenderName <sender@example.com>"` with your verified sender email address from your SMTP2GO account.
- This code uses `HttpJob` which is part of B4J's networking capabilities. Make sure you have configured the necessary permissions for network access if you're deploying this on a platform that requires such permissions.
- The `Wait For` statement is used here for simplicity. In a production environment with more complex logic, you might want to handle the response in a separate event handler for better control over asynchronous operations.
- Error handling in this example is basic. In a real-world scenario, you'd want more comprehensive error handling and possibly retry logic for failed attempts.

This subroutine sends a simple text email. If you need to send HTML emails or include attachments, you would need to modify the JSON payload accordingly, adding parameters like `html_body` for HTML content or an `attachments` array for files.

The main thing was line 16. I didn't have .ToString at the end of my Json send.
Also of note is that is used the SetHeader("Content-Type", "application/json") instead of j.GetRequest.SetContentType("application/json")

It failed the first time I tried it, then I used the SetContentType syntax and I'm working.

Thanks for the feedback!!
Jim
 
Upvote 0
Top