B4J Code Snippet [B4X] Solving encoding issues with html mails sent with SMTP (Net library)

Encoding the html text with base64 avoids encoding issues, especially with MS Outlook.
This code is compatible with B4A and B4J:
B4X:
Dim su As StringUtils
smtp.Body = su.EncodeBase64(html.GetBytes("utf8")) 'html = the html body
smtp.AdditionalHeaders.Put("Content-Transfer-Encoding", "BASE64")

Note that it will not work with messages with attachments.
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
Use this sub if you need to send mail with attachments:
B4X:
'Each item in the Attachments list is an array with the file directory and name.
Sub CreateHtmlAndAttachmentsBody (smtp As SMTP, Html As String, Attachments As List)
    Dim sb As StringBuilder
    sb.Initialize
    Dim eol As String = Chr(13) & Chr(10)
    Dim bound As String = "asdasdwdwqd__HV_qwdqwdddwq"
    sb.Append("--").Append(bound).Append(eol)
    sb.Append($"Content-Type: text/html; charset="utf-8""$).Append(eol)
    sb.Append("Content-Transfer-Encoding: base64").Append(eol).Append(eol)
    sb.Append(EncodeBase64WithLineBreaks(Html.GetBytes("utf8")))
    For Each DirAndName() As Object In Attachments
        sb.Append(eol).Append("--").Append(bound).Append(eol)
        sb.Append("Content-Type: application/octet-stream").Append(eol)
        sb.Append("Content-Transfer-Encoding: base64").Append(eol)
        sb.Append($"Content-Disposition: attachment; filename="${DirAndName(1)}""$).Append(eol).Append(eol)
        sb.Append(EncodeBase64WithLineBreaks(File.ReadBytes(DirAndName(0), DirAndName(1)))).Append(eol)
    Next
    sb.Append("--").Append(bound).Append("--")
    smtp.Body = sb.ToString
    smtp.AdditionalHeaders.Put("Content-Type", $"multipart/mixed; boundary="${bound}""$)
End Sub

Private Sub EncodeBase64WithLineBreaks (bytes() As Byte) As String
    Dim su As StringUtils
    Dim s As String = su.EncodeBase64(bytes)
    If s.Length <= 76 Then Return s
    Dim sb As StringBuilder
    sb.Initialize
    Dim linelength As Int
    For i = 0 To s.Length - 1
        If linelength = 76 Then
            sb.Append(Chr(13) & Chr(10))
            linelength = 0
        End If
        sb.Append(s.CharAt(i))
        linelength = linelength + 1
    Next
    Return sb.ToString
End Sub

Usage example:
B4X:
Dim smtp As SMTP
smtp.Initialize("...", 587, "...", "...", "smtp")
smtp.To.Add("someone@gmail.com")
smtp.Subject = "subject"
Dim html As String = File.ReadString(...)
Dim attachments As List
attachments.Initialize
attachments.Add(Array(File.DirAssets, "some file"))
attachments.Add(Array("C:\Users\H\Documents", "another file"))
CreateHtmlAndAttachmentsBody(smtp, html, attachments)
smtp.Send
Wait For smtp_MessageSent(Success As Boolean)
Log(Success)
 
Last edited:
Top