Android Question Decode Base64 eMail body?

William Hunter

Active Member
Licensed User
Longtime User
I found the code below on the B4J side, at the link below:

https://www.b4x.com/android/forum/threads/decode-email-body-solved.53830/

I want to use this code to decode base64 in a B4A project. I see the notation that it requires Java 8. I have java 8 installed, yet I get the error - java.lang.ClassNotFoundException: java$util$Base64. I’m not sure whether this means B4A doesn’t know Base64, or if there is something wrong with my B4A Paths. It seems odd that B4J passes this code while B4A does not.

My Paths Configuration and the Error Log are attached. Is there something in my Paths Configuration that should be changed? Any help greatly appreciated. :)
B4X:
Sub DecodeB64(Mess As String)
   jo.InitializeStatic("java.util.Base64")
  decoder = jo.RunMethod("getMimeDecoder", Null)
  buf = decoder.RunMethod("decode", Array(Mess))
  Dim news As String
  For Each c As Byte In buf
  news = news & Chr(c)
  Next
    Log("DECODED = : "&news)  'Decoded Message!
End Sub
B4X:
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
Error occurred on line: 4754 (Main)
java.lang.ClassNotFoundException: java$util$Base64
   at java.lang.Class.classForName(Native Method)
   at java.lang.Class.forName(Class.java:309)
   at java.lang.Class.forName(Class.java:273)
   at anywheresoftware.b4j.object.JavaObject.getCorrectClassName(JavaObject.java:273)
   at anywheresoftware.b4j.object.JavaObject.InitializeStatic(JavaObject.java:74)
   at mail.purge.whapp.main._decodeb64(main.java:6940)
   at mail.purge.whapp.main._pop_downloadcompleted(main.java:10919)
   at java.lang.reflect.Method.invoke(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:372)
   at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:703)
   at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:340)
   at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:247)
   at java.lang.reflect.Method.invoke(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:372)
   at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
   at anywheresoftware.b4a.BA$2.run(BA.java:328)
   at android.os.Handler.handleCallback(Handler.java:739)
   at android.os.Handler.dispatchMessage(Handler.java:95)
   at android.os.Looper.loop(Looper.java:135)
   at android.app.ActivityThread.main(ActivityThread.java:5257)
   at java.lang.reflect.Method.invoke(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:372)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.lang.ClassNotFoundException: Didn't find class "java$util$Base64" on path: DexPathList[[zip file "/data/app/mail.purge.whapp-3/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
   at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
   ... 24 more
   Suppressed: java.lang.ClassNotFoundException: java$util$Base64
     at java.lang.Class.classForName(Native Method)
     at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
     at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
     ... 25 more
   Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
** Activity (main) Pause, UserClosed = true **
Paths.png
 

William Hunter

Active Member
Licensed User
Longtime User
You don't need Java to do this :) Just use the StringUtils library:

B4X:
Dim su As StringUtils
FileString64=su.EncodeBase64(ImageBytes)
FileBytes=su.DecodeBase64(FileString64)
Thank you KMatle. In reading at the B4J posting, I get the impression that this Sub is used to decode messages in mime. I would like to experiment with it to see exactly what it does do. I have used StringUtils to decode Base64 text in Mailparser by adding the code shown below. I've been struggling to decode mime messages as well as trying to extract HTML, without much success. I would like to experiment with this java suggestion, but can't get it to work. I would like to know why.

Best regards :)
B4X:
Sub HandlePart(Headers As String, Body As String, Msg As Message)
   If Regex.Matcher2("Content-Transfer-Encoding:\s*base64", _
     Regex.CASE_INSENSITIVE, Headers).Find Then
     'we are dealing with an attachment
     Dim filename As String
     Dim m As Matcher
     m = Regex.Matcher2("filename=\s*q([^q]+)q".Replace("q", QUOTE), Regex.CASE_INSENSITIVE, Headers)
     If m.Find Then filename = m.Group(1) Else filename = "attachment" & (Msg.Attachments.Size + 1)
     Dim su As StringUtils
     Dim out As OutputStream
     out = File.OpenOutput(dir, filename, False)
     Dim data() As Byte
     data = su.DecodeBase64(Body)
     'Log("file saved: "  & filename & " (" & data.Length & " bytes)")
     out.WriteBytes(data, 0, data.Length)
     out.Close
     Msg.Attachments.Add(filename)
     ' My code changes start here
     If Regex.Matcher2("Content-Type:\s*text/plain", _
       Regex.CASE_INSENSITIVE, Headers).Find Then
       'Log("Msg is text/plain")
       'File.WriteString(File.DirRootExternal, "BodyTextPlain1.txt", Body) ' for testing only
       Dim su As StringUtils
       Dim b() As Byte = su.DecodeBase64(Body)
       Body = BytesToString(b, 0, b.Length, "UTF8")
       'File.WriteString(File.DirRootExternal, "BodyTextPlain2.txt", Body) ' for testing only
       Msg.Body = Body
     End If
     ' my code changes end here
   Else If Regex.Matcher2("Content-Type:\s*text/", _
     Regex.CASE_INSENSITIVE, Headers).Find Then
     'Log("Msg is text")
     'File.WriteString(File.DirRootExternal, "BodyText.txt", Body) ' for testing only
     Msg.Body = Body
   End If
End Sub
 
Upvote 0

William Hunter

Active Member
Licensed User
Longtime User
It may be that the solution posted at the B4J side has a missing library reference. The code on which the solution is based was provided by Daestrum, a member other than the poster of the solution. Daestrum’s code has a reference to the B4J JFX library. It may that Android does not support JavaFX. If this is why a JFX library is not available for B4A I would appreciate confirmation of this. I've gone up so many blind alleys with this, I'm starting to get a pug nose. :(

Also, is there a means of extracting the HTML portion of a message? If anyone has found a means of decoding mail types beyond those currently supported by the MailParser, and is willing to share their knowledge, their help would be greatly appreciated.

Best regards :)
 
Upvote 0

William Hunter

Active Member
Licensed User
Longtime User
This code, utilizing the StringFunctions library, will extract HTML from an non truncated message. While I have had modest success using it, it is not reliable enough for general use. In order to handle all the content-type/encoding possibilities the MailParser would require modifications that are beyond my limited abilities.

Regards :)
B4X:
YourMsg = ExtractHTML(YourMsg)

Sub ExtractHTML(b As String) As String
   If b.Contains("<html>") And b.Contains("</html>") = True Then
     'Log(b)
     b = Main.sf.MidExtract(b, "<html>", "</html>")
     b = Main.sf.Pad(b, "<html>", 1, False)
     b = Main.sf.Pad(b, "</html>", 1, True)
   End If
   Return b
End Sub
 
Upvote 0
Top