B4A Library New Net library - Android FTP, SMTP and POP3

Status
Not open for further replies.

Harris

Expert
Licensed User
Longtime User
Here is a copy of my code - whenever one has a chance to review. The MessageSent event has been moved to an activity module to capture event.
SMTP params were derived from a Map file (created in my setup)

Thanks

Sub Process_Globals
'These global variables will be declared once when the application starts.
'These variables can be accessed from all modules.


Dim SMTP1 As SMTP


Dim myserver, myadd, mypass, myto1, myto2, myto3 As String
Dim myport As Int
Dim myssl,wassent As Boolean



End Sub


Sub QueMail
Dim C1 As Cursor
Dim i As Int

' que up out going mail

C1 = DefCM.SQL1.ExecQuery2( "SELECT * FROM Inspections WHERE Sent = ?", Array As String(0) )
If C1.RowCount > 0 Then

SendSetup ' setup the SMTP object for sending
For i = 0 To c1.RowCount - 1
c1.Position = i
wassent = False
' open send session
Dim Recno As Long
Dim Name, From As String
Dim buf() As Byte

Buf = C1.GetBlob("Inspect")
Recno = c1.GetLong("ID_Date")
Name = c1.GetString("Name")
From = " "
From = From &c1.GetString("Trip")&" For: "
From = From &c1.GetString("Driver")&" Truck: "
From = From &c1.GetString("Truck")&" Trailer: "
From = From &c1.GetString("Trailer")



Dim out As OutputStream
out = File.OpenOutput( File.DirDefaultExternal&"/InspForms/",Name, False)
out.WriteBytes(buf,0,buf.Length )
out.Flush
out.Close
Log(" Write pdf to disk for sending: "&Name)
DoEvents

If SendFile(Name, From) = True Then
If wassent Then
Log(" Mail WAS Sent: "&Name)
UpDateSent(Recno)
Else
Log(" Mail WAS NOT Sent: "&Name)
End If
End If

'File.Delete(File.DirDefaultExternal&"/InspForms/",Name)
Next
Else
ToastMessageShow(" No Reports to Send Were Found",True)
End If
C1.Close

End Sub


Sub SendFile(Name As String, From As String) As Boolean

SMTP1.To.Add(myto1)
If myto2.Length > 0 Then
SMTP1.CC.Add(myto2)
End If
If myto3.Length > 0 Then
SMTP1.CC.Add(myto3)
End If
' SMTP1.HtmlBody = False
SMTP1.Subject = "MySite.com: "&Name
SMTP1.Body = From&CRLF&CRLF&CRLF&" ***COPYRIGHT*** "&CRLF&" MYSITE.COM "&CRLF&" ALL RIGHTS RESERVED "
SMTP1.AddAttachment(File.DirDefaultExternal&"/InspForms/",Name)
SMTP1.Send

Log("Attempted to Send May Have Failed: ")

DoEvents
Return True
End Sub



' MOVED TO ACTIVITY MODULE
'Sub SMTP1_MessageSent(Success As Boolean)
'
'Log (" Message Sent: "&Success)
'If Success Then
' wassent = True
'Else
' wassent = False
' Log("Send Error: "&LastException.Message)
'End If
'
'
'End Sub



Sub UpDateSent(rec As Long)

Defcm.SQL1.ExecNonQuery2("UPDATE Inspections SET Sent = ? WHERE ID_Date = ?", Array As String(DateTime.Now,rec))

End Sub

Sub SendSetup
' setup the SMTP object
Dim mp As Map


mp.Initialize
If File.Exists(File.DirDefaultExternal,"smtp.map") Then
mp = File.ReadMap(File.DirDefaultExternal,"smtp.map")
Else
ToastMessageShow(" SMTP Setup File Not Found",False)
End If

myServer = mp.Get("smtpserver")
myadd = mp.Get("smptname")
mypass = mp.Get("smtppass")
myport = mp.Get("smtpport")
myssl = mp.Get("cbsmtpssl")

myto1 = mp.Get("to1")
myto2 = mp.Get("to2")
myto3 = mp.Get("to3")

SMTP1.Initialize(myServer,myport,myadd,mypass,"SMTP1")
SMTP1.UseSSL=True

Msgbox(" SMTP: "&myServer&" "&myadd&" "&mypass&" "&myport&" "&myssl&" Send To: "&myto1," SMTP ")


End Sub
 

Harris

Expert
Licensed User
Longtime User
Sorry vb, DefCM is my default code module - where SQL1 is inited.

The globals contain SMTP1 and user password for priming SMTP1.Intialize.

Funny, I had it all working - sending my pdfs like clockwork then - server responds with Authentication Required....

I setup outlook with the same user and password and get the same result. Must be something with my username and password for that test account.
My tester set my app up with a different account and gets the same return result - no sending

I created a little stub, based on code above and can't seem to get passed it. Time to install 1.8 and then work beyond this.

I will setup a new google email account and see how that flies.

Thanks
 

Harris

Expert
Licensed User
Longtime User
I have it working with my own personal account such as: myaccount@gmail.com.

However, I ask my friend who was having issue with the same test app to use my account. He didn't get anywhere... The MessageSent event error he gets on his Galaxy S2 is:
java.net.ConnectionException: localhost/::1:465 - Connection refused.

LocalHost??? wtf?

This is the same he will get using any of his valid email accounts with gmail.

When i try to use another valid gmail account (which worked when I first tried SMTP), I get:
Send Error: java.lang.RuntimeException: Empty writer returned: 530-5.5.1 Authentication Required. Learn more at mail.google.....

I will post my complete test app code to see if anyone else sees the same.

Thanks
 

Harris

Expert
Licensed User
Longtime User
Attached is a simple sample of the test smtp.

My primary account works, were as many other accounts produce erros in the connection.

Thanks
 

Attachments

  • testsmtp.zip
    10 KB · Views: 660

vb1992

Well-Known Member
Licensed User
Longtime User
what happens when you test the basics out?

B4X:
Sub Process_Globals
    Dim SMTP As SMTP
End Sub
Sub Globals

End Sub

Sub Activity_Create(FirstTime As Boolean)
    If FirstTime Then
        SMTP.Initialize("smtp.gmail.com", 465, "XXX@gmail.com", "XXX", "SMTP")
        SMTP.UseSSL = True 'Gmail requires SSL.
    End If
    SMTP.To.Add("X@X.COM")
    SMTP.Subject = "This is the subject"
    SMTP.Body = "This is the message body."
    'SMTP.AddAttachment(File.DirRootExternal, "somefile")
    SMTP.Send
End Sub
Sub SMTP_MessageSent(Success As Boolean)
    Log(Success)
    If Success Then
        ToastMessageShow("Message sent successfully", True)
    Else
        ToastMessageShow("Error sending message", True)
        Log(LastException.Message)
    End If
End Sub



Have you read up on the PORTS?

 
Last edited:

Harris

Expert
Licensed User
Longtime User
Local host issue solved:
Seems the hint color is very close to a valid input color on some devices - and possibly the age of ones eyes plays a role. My tester did not supply a server value because the hint said: smpt.gmail.com My bad.. never supply valid values as hints.... :sign0013:

As for my other valid address to the same gmail server, I will try your basic code above. You saw my test app is not far from your code above?

Also, it would be nice to associate a send request with an ID. That way, I could determine which mail actually "made it" and which ones failed. With the ID, I could then update my tables record with the Sent flag and delete the file I extracted from my blob. Testing with the S2 this am, the mail was received long before (about 2 minutes) the ack came back from the server (Success) saying it was sent. This was due to low signal strength (I assume). When the same test was tried with phone in the signal booster, Success was received right away.

Any suggestions on how to handle this would be most welcome. I have even tried waiting for the event directly after a send. I don't see the event until I exit the loop however long I wait..

SMTP.Send
do while MsgEvent = False
DoEvents
cnt = cnt + 1
if cnt > 2000 then Exit
loop

In the event, I set MsgEvent to True when it fires, however it never does....

Thanks everyone
 

vb1992

Well-Known Member
Licensed User
Longtime User
As for my other valid address to the same gmail server, I will try your basic code above. You saw my test app is not far from your code above?

I just know that code above works, with my gmail,
so I figured if you can test that other gmail
account with it, we are comparing apples to apples
 

Harris

Expert
Licensed User
Longtime User
My other account now works!
GMail was wanting me to authenticate this account. I only used it for testing on my device so I wasn't aware that it needed me to do this since this account was not listed in my gmail. Now that I have done this, it works fine - no error requesting authenication - as posted above.

Yes, the sample code functions fine. Any suggestions about handling multiple mail send and confirmations?
Thanks
 

Harris

Expert
Licensed User
Longtime User
However the best approach is to wait for one message to be sent and then send the next one in MessageSent event.

So, if I understand this correctly:
I have 10 mails to send, create a list of these mails - que up and send the first one. Wait for response in MessageSent event (update list of pass or fail). In MessageSent, check if more mails need to be sent in list. Repeat... to end of list. When entire list has been processed, update my db table with results from list (mark sent field accordingly) and clean up files on disk (attachments).

Sounds recursive but I think I can handle it.

Thanks
 

Smee

Well-Known Member
Licensed User
Longtime User
I am sending emails ok but the SMTP1_MessageSent(Success As Boolean) sub is not firing. I am using a code module for all routines

does it have to be used in activity mod?
 

Harris

Expert
Licensed User
Longtime User
YES, the event must be in activity module.... That was my problem (among others).

I have SMTP sending multiple mails working now...

I dont think its pretty, but it works

I can update my db when the mail was sent and clean up left over files that were the attachments. Keep a clean house (wish I could say for my own - maid wanted...).
 

Smee

Well-Known Member
Licensed User
Longtime User
I do not know what is wrong but the SMTP1_MessageSent(Success As Boolean) sub is still not firing.

I have putting all the code in the Main Activity Module, Code Module and Service Module.
This is how i send
B4X:
SMTP1.Initialize(server, port, emailname, Password, protocol)
SMTP1.UseSSL=True
SMTP1.To.Add(Receiver)
SMTP1.Subject = Subject
SMTP1.Body = Body
SMTP1.AddAttachment(DirName, FileName)
SMTP1.Send

Sub SMTP1_MessageSent(Success As Boolean)

log( Success )

end sub

i have tried putting the dim smtp1 in process globals and globals all without success
 

Smee

Well-Known Member
Licensed User
Longtime User
:sign0148:

don' t know where i got the protocol from??? I think it was when i looked up Gmail requirements.

Anyway i changed to "SMTP1" and it works beautifully.

Thank you

FWIW to any others, I changed all the code and put it into a Service Module and it runs great in the background. The program keeps running whilst all emails are being silently sent.
 

Harris

Expert
Licensed User
Longtime User
Yes, good idea.
I have accomplished what I wanted and have mine in a code module - "attempting" to send when I return to the main form (as would be normal in my app). However, in a service module, it could attempt always and often until all mails went out. My users have limited connection through tablets and areas not served well by cell coverage. This would ensure it would get out when it could.
I shall convert my app pronto...

Thanks all....
 

cirollo

Active Member
Licensed User
Longtime User
Error using the new net library

I was using the network library
I needed the passivemode property so I used the net 1.20 library deselecting the network library

I'm getting this when compiling

B4X:
Compiling code.                         0.75
Generating R file.                      0.00
Compiling generated Java code.          2.59
Convert byte code - optimized dex.      Error
UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.IllegalArgumentException: already added: Lorg/apache/commons/net/DatagramSocketClient;
   at com.android.dx.dex.file.ClassDefsSection.add(ClassDefsSection.java:123)
   at com.android.dx.dex.file.DexFile.add(DexFile.java:163)
   at com.android.dx.command.dexer.Main.processClass(Main.java:486)
   at com.android.dx.command.dexer.Main.processFileBytes(Main.java:455)
   at com.android.dx.command.dexer.Main.access$400(Main.java:67)
   at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:394)
   at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:245)
   at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:131)
   at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:109)
   at com.android.dx.command.dexer.Main.processOne(Main.java:418)
   at com.android.dx.command.dexer.Main.processAllFiles(Main.java:329)
   at com.android.dx.command.dexer.Main.run(Main.java:206)
   at com.android.dx.command.dexer.Main.main(Main.java:174)
   at com.android.dx.command.Main.main(Main.java:95)
1 error; aborting
   Standard dexer.

why???
 

biometrics

Active Member
Licensed User
Longtime User
Is FTP Resume Supported?

Hi Erel,

Is FTP resume supported? Does the library do it automatically or should I send a resume command first using SendCommand before DownloadFile?
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…