B4J Question Decode Email Body? - SOLVED!

aidymp

Active Member
Licensed User
Hi, Im using the Mini Email Server example. and have posted this question in there, but it is possibly better to post it here!

Basically I get an email from a third party selling site, (the email address is a unique one for each customer, so 542895645975@reply.blah.com) if i reply to that address the mail does go to them customer, but in some cases it is lost or sometimes takes quite a while to get there. The Email body (in an email program contains the real email of the customer) So i (Well Erel!) made a sub to extract the email and reply to that instead! it works fine if i email it! (from say gmail or similar) But when I try with the real emails it never extracts an email address! after messing with the code for quite some time, I decided to look at the message body, its in some sort of code! and not what I was expecting! which is why the extraction routine wont find it!

this is what im getting

Msg.body= CgoKPCFET0NUWVBFIGh0bWw+CjxodG1sPgogICAgPGhlYWQ+Cgk8bWV0YSBj
b250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9dXRmLTgiIGh0dHAtZXF1aXY9
IkNvbnRlbnQtVHlwZSI+Cgk8dGl0bGU+U2VsejwvdGl0bGU+Cgk8bGluayBy
ZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vZDMzaTYyNHB3NmpqNjgu
Y2xvdWRmcm9udC5uZXQvc3RhdGljL2Nzcy8yL2VtYWlscy5jc3MiPgoJPHN0
eWxlPgoJQG1lZGlhIG9ubHkgc2NyZWVuIGFuZCAobWF4LXdpZHRoOiA2NDBw
eCkgewoJCWJvZHkgewoJCQltaW4td2lkdGg6IDMyMHB4OwoJCX0KCQkuYm9k
eS1jb250YWluZXIgewoJCQl3aWR0aDogOTUlOwoJCX0KCQkuY3RhLWJhciBp
bWcgewoJCQl3aWR0aDogYXV0bzsKCQkJbWF4LXdpZHRoOiAxMDAlOwoJCX0K
CQkucm93LXNwYWNlciB7CgkJCWhlaWdodDogMTVweCAhaW1wb3J0YW50OwoJ
CX0KCQkuZml4ZWQsCgkJLmZpeGVkIGltZyB7CgkJCXdpZHRoOiBhdXRvICFp
bXBvcnRhbnQ7CgkJCW1heC13aWR0aDogMTAwJTsKCQl9Cgl9Cgk8L3N0eWxl
Pgo8L2hlYWQ+CiAgICA8Ym9keSBiZ2NvbG9yPSIjRjhGQUZCIiBzdHlsZT0i
bWFyZ2luOiAwOyBwYWRkaW5nOiAwOyBiYWNrZ3JvdW5kOiAjRjhGQUZCOyBo
ZWlnaHQ6IDEwMCU7IHdpZHRoOiAxMDAlICFpbXBvcnRhbnQ7IC13ZWJraXQt
dGV4dC1zaXplLWFkanVzdDpub25lOyI+CiAgICAgICAgPHRhYmxlIGJvcmRl
cj0iMCIgY2VsbHBhZGRpbmc9IjAiIGNlbGxzcGFjaW5nPSIwIiBzdHlsZT0i
YmFja2dyb3VuZC1jb2xvcjogI0Y4RkFGQiIgd2lkdGg9IjEwMCUiIGFsaWdu
PSJjZW50ZXIiPgogICAgICAgICAgICA8dHI+CiAgICAgICAgICAgICAgICA8
dGQgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNGOEZBRkIiIHdpZHRoPSIx
MDAlIiBhbGlnbj0iY2VudGVyIj4KICAgICAgICAgICAgICAgICAgICA8aW1n
IHNyYz0iaHR0cHM6Ly9zZWx6aW1nLnMzLmFtYXpvbmF3cy5jb20vZW1haWwv
dHJhbnNwYXJlbnQuZ2lmIiBjbGFzcz0icm93LXNwYWNlciIgaGVpZ2h0PSIy
b2NrIj4KICAgICAgICAgICAgICAgICAgICA8cCBzdHlsZT0ibWFyZ2luOiAw
OyBwYWRkaW5nOiAwOyI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxhIGhy
ZWY9IiIgdGFyZ2V0PSJfYmxhbmsiIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb246
IHVuZGVybGluZTsgY29sb3I6ICM3MzRiY2M7Ij4KICAgICAgICAgICAgICAg
ICAgICAgICAgICAgIDxpbWcgc3JjPSJodHRwczovL3NlbHppbWcuczMuYW1h
em9uYXdzLmNvbS9lbWFpbC9sb2dvLmdpZj92MiIgYm9yZGVyPSIwIiB3aWR0
aD0iNzAiIGhlaWdodD0iNDEiIGFsdD0iU2VseiI+CiAgICAgICAgICAgICAg
ICAgICAgICAgIDwvYT4KICAgICAgICAgICAgICAgICAgICA8L3A+CiAgICAg
ICAgICAgICAgICAgICAgPGltZyBzcmM9Imh0dHBzOi8vc2VsemltZy5zMy5h
bWF6b25hd3MuY29tL2VtYWlsL3RyYW5zcGFyZW50LmdpZiIgY2xhc3M9InJv
dy1zcGFjZXIiIGhlaWdodD0iMjUiIHN0eWxlPSJ2ZXJ0aWNhbC1hbGlnbjog
bWlkZGxlOyBkaXNwbGF5OiBibG9jayI+ICAgICAgICAgICAgIAogICAgICAg
ICAgICAgICAgICAgIDx0YWJsZSBhbGlnbj0iY2VudGVyIiBib3JkZXI9IjAi
IGNlbGxwYWRkaW5nPSIwIiBjZWxsc3BhY2luZz0iMCIgd2lkdGg9IjYwMCIg
Y2xhc3M9ImJvZHktY29udGFpbmVyIj4KICAgICAgICAgICAgICAgICAgICAg
ICAgPHRyPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNz
PSJwYWdlIiB3aWR0aD0iMTAwJSIgc3R5bGU9Ii1tb3otYm9yZGVyLXJhZGl1
czogNHB4OyAtd2Via2l0LWJvcmRlci1yYWRpdXM6IDRweDsgYm9yZGVyLXJh
ZGl1czogNHB4OyAtbW96LWJveC1zaGFkb3c6IDBweCAxcHggM3B4IHJnYmEo
MCwwLDAsMC4yKTsgLXdlYmtpdC1ib3gtc2hhZG93OiAwcHggMXB4IDNweCBy
Z2JhKDAsMCwwLDAuMik7IGJveC1zaGFkb3c6IDBweCAxcHggM3B4IHJnYmEo
MCwwLDAsMC4yKTsgYmFja2dyb3VuZC1jb2xvcjogI2ZmZmZmZjsiPgogICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0YWJsZSBib3JkZXI9IjAi
IGNlbGxwYWRkaW5nPSIwIiBjZWxsc3BhY2luZz0iMCIgd2lkdGg9IjEwMCUi
IGNsYXNzPSJjb250YWluZXIiPgogICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICA8dHI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg

Im not sure how to convert it to back to plain text. the actual email is HTML, but im sure once i can see the html, i would be able to still see the email address?

Any clues or help appreciated!

Thanks

Aidy
 

Daestrum

Well-Known Member
Licensed User
To get the message into human readable format you need to use base64decode.
start of your message:
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>Selz</title>
<link rel="stylesheet" href="https://d33i624pw6jj68.cloudfront.net/static/css/2/emails.css">
<style>
@media only screen and (max-width: 640px) {
body {
min-width: 320px;
}
.body-container {
width: 95%;
}
.cta-bar img {
width: auto;
max-width: 100%;
}
.row-spacer {
height: 15px !important;
}
.fixed,
.fixed img {
width: auto !important;
max-width: 100%;
}
}
</style>
</head>
 

aidymp

Active Member
Licensed User
To get the message into human readable format you need to use base64decode.
start of your message:
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>Selz</title>
<link rel="stylesheet" href="https://d33i624pw6jj68.cloudfront.net/static/css/2/emails.css">
<style>
@media only screen and (max-width: 640px) {
body {
min-width: 320px;
}
.body-container {
width: 95%;
}
.cta-bar img {
width: auto;
max-width: 100%;
}
.row-spacer {
height: 15px !important;
}
.fixed,
.fixed img {
width: auto !important;
max-width: 100%;
}
}
</style>
</head>
Any chance of some example code? I have tried various snippets, but they seem to fail to do anything, basically the ones I tried I don't understand what parameters they are asking for! (im still quite new) i tried this

B4X:
Sub UnMIME(s2match As String, CharSet As String) As String
Dim m As Matcher
Dim cnv As ByteConverter
Dim SupportedEncodings() As String
Dim booCharSetIsValid As Boolean
Dim c2match As String
Dim j As Int

SupportedEncodings = cnv.SupportedEncodings

booCharSetIsValid = False
For j = 0 To SupportedEncodings.Length - 1
    If CharSet.ToUpperCase = SupportedEncodings(j).ToUpperCase Then
      booCharSetIsValid = True
    End If      
Next

If booCharSetIsValid = True Then
  If CharSet.Trim.ToLowerCase = "utf-8" Then
      c2match = "=[0-9a-fA-F][0-9a-fA-F]=[0-9a-fA-F][0-9a-fA-F]"
  Else
      c2match = "=[0-9a-fA-F][0-9a-fA-F]"
      s2match = s2match.Trim
      s2match = s2match.Replace(" ","=20")
      If s2match.EndsWith("=") = True Then
        s2match = s2match.SubString2(0,s2match.Length-1)
      End If    
  End If
  m = Regex.Matcher(c2match,s2match)
  Do While m.Find = True
      s2match = s2match.Replace(m.Group(0), cnv.StringFromBytes(cnv.HexToBytes(m.Group(0).Replace("=","")), CharSet))
      m = Regex.Matcher(c2match,s2match)
  Loop
End If

Return s2match

End Sub
And called it with this!

B4X:
Log(UnMIME(msg.Body,"UTF-8"))
But that did not seem to change the result, i get back, what i passed it!


So I tried this

B4X:
Dim b() As Byte = Messagetext.GetBytes("ISO-8859-1")
   Log(BytesToString(b, 0, b.Length, "UTF8"))
Which gave me lots of information about the message, but not anything containing the message body. I think some of the problem is that I dont understand, that particular code! as in what is b? and what this does "Messagetext.GetBytes"

if i try the above with msg.body as in

B4X:
Dim b() As Byte = msg.body.GetBytes("ISO-8859-1")
   Log(BytesToString(b, 0, b.Length, "UTF8"))
I just get an error! regarding the getbytes.

Im stuck! lol

So Any clue as to somethng I can just pass the original msg.body to and get the decoded result back would be a great help!

Im thinking its something simple. but as i said debugging is hard has i have to work with the real message, and they only sell around 7 a day! so i have 7 chances to try something new!

Thanks

Aidy
 

Daestrum

Well-Known Member
Licensed User
If you are running java 8 then this will decode it for you. (there's probably a library but I never looked for it)
B4X:
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Dim decoder,jo As JavaObject
    Dim buf() As Byte
    Dim s As String

End Sub
Sub AppStart (Form1 As Form, Args() As String)
'paste your long string between the $" ..."$ or just set s = to the string    
s = $"..."$
    jo.InitializeStatic("java.util.Base64")
    decoder = jo.RunMethod("getMimeDecoder",Null)
    buf = decoder.RunMethod("decode",Array(s))
    Dim news As String
    For Each c As Byte In buf
        news = news & Chr(c)
    Next
    Log(news)
    MainForm = Form1
    'MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
    MainForm.Show
End Sub
 

aidymp

Active Member
Licensed User
If you are running java 8 then this will decode it for you. (there's probably a library but I never looked for it)
B4X:
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Dim decoder,jo As JavaObject
    Dim buf() As Byte
    Dim s As String

End Sub
Sub AppStart (Form1 As Form, Args() As String)
'paste your long string between the $" ..."$ or just set s = to the string  
s = $"..."$
    jo.InitializeStatic("java.util.Base64")
    decoder = jo.RunMethod("getMimeDecoder",Null)
    buf = decoder.RunMethod("decode",Array(s))
    Dim news As String
    For Each c As Byte In buf
        news = news & Chr(c)
    Next
    Log(news)
    MainForm = Form1
    'MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
    MainForm.Show
End Sub
Thank you so much! the above code works perfect!

You and others in this forum, make B4X GREAT!!!

Do you have PayPal so i can buy you a drink?

Thanks

Aidy
 

aidymp

Active Member
Licensed User
For future reference (REQUIRES JAVA 8)

B4X:
Sub Process_Globals
Dim decoder,jo AsJavaObject
Dim buf() As Byte
End Sub

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

'Usage
Log(DecodeB64(Encodedstring))
Solved by Daestrum

Thanks

Aidy
 

Daestrum

Well-Known Member
Licensed User
You can condense the code and remove the 'nasty' for-each loop as java can convert byte array to String itself. (just add another javaobject jo1)
B4X:
    decoder = jo.InitializeStatic("java.util.Base64").RunMethod("getMimeDecoder",Null)
    Dim news As String = jo1.InitializeNewInstance("java.lang.String",Array(decoder.RunMethod("decode",Array(s))))
    Log(news)
 

William Hunter

Active Member
Licensed User
I want to use the code in post #6 above, to decode base64. 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.

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:
** 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
 

aidymp

Active Member
Licensed User
I want to use the code in post #6 above, to decode base64. 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.

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:
** 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 **
View attachment 47336
My email server was very buggy to say the least, and any change to the incoming email crashed the system, so i abandoned the project. however the first thing I notice about your app, is your using B4A! and I was using B4J so maybe that is part of your problem??

Thanks

Aidy
 

William Hunter

Active Member
Licensed User
My email server was very buggy to say the least, and any change to the incoming email crashed the system, so i abandoned the project. however the first thing I notice about your app, is your using B4A! and I was using B4J so maybe that is part of your problem??

Thanks

Aidy
Thank you Aidy. As I understand it B4A and B4J are almost identical, with most coding usable on both platforms, except for some coding affecting the interface. I need a little expert help from someone with a better understanding of Java than I have. I don't understand why I'm getting the error.

Regards

Edit: Aidy, I notice that Daestrum has a reference to the JFX library (Private fx As JFX) in the code he provided to you, whereas this is not included in your solution. This may be the source of my problem. There is not a JFX library for B4A. It may be that Android does not support JavaFX, so I may be hooped on this one. You might want to check your posted solution, just in case the reference to the JFX library was unintentionally omitted. ;)
 
Last edited:
Top