I used javamail api in my android project and parse String in "mail subject" and "mail content". In my gmail there are many mail boxes such as travel, job, photo.... I need go through all mail boxes and search mails in my conditions. But I found when call getData() it will login gmail and make connection again.
My question are
1.How can it Keep connection in android?
2.How can I search all the mail boxes in the same time?
Thanks for help.
private String downloadUrl () throws IOException {
receiveMail("username", "password");
return null;
}
receiveMail part
private static List<Message> receiveMail(String username, String Password) {
try {
Properties props = System.getProperties();
props.setProperty("mail.store.protocol", IMAPS_PROTOCOL);
Session session = Session.getDefaultInstance(props, null );
session.setDebug(false);
final Store store = session.getStore(IMAPS_PROTOCOL);
store.connect(IMAPS_MAIL_HOTS , username, Password);
getData(store, "travel");
getData(store, "job");
getData(store, "photo");
} catch(Exception ex) {
ex.printStackTrace();
}
return null;
}
If you want to reuse a single connection for each folder, you need to be sure to close the folder before opening the next folder.
Related
My app sends an activation code to email during user's registration process, but for an unknown -to me- reason in some Chinese devices is not working and I'm not being able to get a log of the Exception.
This is where I send the email:
private void getAwsResult_getAwsUser(String strResult)
{
try{
CommunityUserDTO communityUser = CommunityUserService.deserializeUser(strResult);
if(communityUser==null){ //email don't exist in database
registerResult.setValue(new Pair<>(null, Enum.RegisterResult.SENDINGEMAIL));
CreateUserUseCase.setActivationCode(this.user);
sendConfirmationEmail(this.user.getEmail(), this.user.getActivationCode());
}else{
registerResult.setValue(new Pair<>(null, Enum.RegisterResult.EMAILALREADYREGISTERED));
}
}catch(Exception ex)
{
ExceptionHandler.logException(ex);
}
}
private void sendConfirmationEmail(String recipient, int activationCode)
{
String jsonEmail = SendEmailUseCase.
generateJsonConfirmationEmail(recipient, activationCode);
TaskRunner taskRunner = new TaskRunner();
taskRunner.executeAsync(new SendEmailTask(jsonEmail), this::getAwsResult_sendEmail);
}
public class SendEmailTask implements Callable<String>
{
private final String jsonEmail;
public SendEmailTask(String jsonEmail)
{
this.jsonEmail = jsonEmail;
}
#Override
public String call()
{
return TMEmail.send(jsonEmail);
}
}
This is a jsonEmail input parameter for sendEmail method example:
{
"subject":"Your activation code.",
"message":"Your activation code is: xxxxxx",
"send_to":"xxx#gmail.com",
"send_from":"contact#xxx.com",
"smtp_server":"xxx.amazonaws.com",
"smtp_user":"xxx",
"smtp_pass":"xxx",
"smtp_useauth":"true",
"smtp_port":"25",
"center_text":"true"
}
public static String send(String jsonEmail)
{
String result = Enum.Result.OK;
JSONObject oJsonEmail = TMJson.str2JSON(jsonEmail);
try {
String subject = oJsonEmail.getString(Enum.Email.SUBJECT);
String message = oJsonEmail.getString(Enum.Email.MESSAGE);
String sendFrom = oJsonEmail.getString(Enum.Email.SEND_FROM);
String sendTo = oJsonEmail.getString(Enum.Email.SEND_TO);
String smtpServer = oJsonEmail.getString(Enum.Email.SMTP_SERVER);
String smtpPort = oJsonEmail.getString(Enum.Email.SMTP_PORT);
String smtpUseAuth = oJsonEmail.getString(Enum.Email.SMTP_USEAUTH);
boolean centerBodyText = Boolean.parseBoolean(oJsonEmail.getString(Enum.Email.CENTER_TEXT));
final String smtpUser = oJsonEmail.getString(Enum.Email.SMTP_USER);
final String smtpPass = oJsonEmail.getString(Enum.Email.SMTP_PASS);
Properties props = new Properties();
props.put("mail.smtp.host", smtpServer);
props.put("mail.smtp.port", smtpPort);
props.put("mail.smtp.auth", smtpUseAuth);
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.from.alias", "My App Name");
Session session = Session.getInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(smtpUser, smtpPass);
}
});
message = TMJson.decodeEmail(message);
message = format(message, centerBodyText);
Message oMessage = new MimeMessage(session);
oMessage.setFrom(new InternetAddress(sendFrom, session.getProperty("mail.from.alias"), "UTF-8"));
oMessage.setRecipients(Message.RecipientType.TO, InternetAddress.parse(sendTo));
oMessage.setSubject(subject);
oMessage.setContent(message, "text/html; charset=iso-8859-2");
Transport.send(oMessage);
}catch (MessagingException | UnsupportedEncodingException | JSONException e) {
result = Enum.Result.KO;
ExceptionHandler.logException(e);
}
return result;
}
I've tested this in my Android mobile and tablet, and in many other devices and it's working just fine, the email is sent and the user receives the activation code, but in China, where we are still testing the beta version the tester is not receiving the email.
I know the app is crashing before sending the email, but cannot figure out why, and if you notice, I hace a try/catch with this ExceptionHandler.logException(e); that sends a report of the crash to my email, but it's also not working, so I don't know what to do.
I contacted AWS support team to check if there is any possibility to see any SES logs, but has no response yet.
Any ideas on how could I get closer to the real exception? Still cannot even see it in the Google Play Developer Console crashes report section.
Ok, luckily I found the issue myself. Nothing to do with Chinese devices, but with Android version.
I was testing my app in Android 10 devices (the only ones I have) and they were testing in an Android 11 device.
This link solved my problem:
Android Studio VerifyError rejecting class text_plain from JavaMail API
And this is the solution: Add this in build.gradle
android {
...
packagingOptions {
exclude 'META-INF/NOTICE.md'
exclude 'META-INF/LICENSE.md'
}
}
dependencies {
implementation 'com.sun.mail:android-mail:1.6.6'
implementation 'com.sun.mail:android-activation:1.6.6'
...
}
Hope I'm helping anyone else having problems sending emails.
I'm using the oauth2-essentials library because it was one of the recommended oauth libraries on the uber developers site, and it has been recently updated.
My code looks like this:
executor = new HttpUrlConnectionExecutor();
OAuth2AuthorizationProvider provider = new BasicOAuth2AuthorizationProvider(
URI.create("https://login.uber.com/oauth/v2/authorize"),
URI.create("https://login.uber.com/oauth/v2/token"),
new Duration(1,0,3600) /* default expiration time in case the server doesn't return any */);
OAuth2ClientCredentials credentials = new BasicOAuth2ClientCredentials(
getString(R.string.uberClientId), getString(R.string.uberSecret));
uberOAuthClient = new BasicOAuth2Client(
provider,
credentials,
new LazyUri(new Precoded("my redirect url")) /* Redirect URL */);
generateUberOAuthToken("my phone number", "my password");
}
public void generateUberOAuthToken(final String uName, final String password){
new Thread() {
public void run() {
try {
uberOAuthToken = new ResourceOwnerPasswordGrant(
uberOAuthClient, new BasicScope("profile"), uName, password).accessToken(executor);
}
catch (Exception e){
e.printStackTrace();
}
}
}.start();
}
The exception: org.dmfs.httpessentials.exceptions.UnauthorizedException: Authentication at 'https://login.uber.com/oauth/v2/token' failed. is always thrown. I've tried removing the redirect url so it should use the default from my dashboard, and I've tried added 1 and/or dashes to the phone number. The exception is always thrown when I request an access token. I know my account is setup correctly because this works fine in iOS. I feel like I must be missing something obvious. Anyone else run into this issue?
The token api did not recognize my phone number as a valid login parameter. It worked when I used my email instead.
I've been working on feedback form. It consists of name,email and feedback EditTexts.
I'm making the android application for the user to send the feedback using JavaMail API. Now My android is working fine as the user inputs the details in the fore mentioned space and sends the feedback to the mail which is given as Recipients address(i.e., My gmail account).
Problem : I have tried my level best to get the data(the mail id of the user)from the EditText input for email id of the user and to show it on the gmail account account as sent by USER_NAME but after numerous efforts it is giving me same data i.e., The mail is sent by me only no user id is shown
I'm providing you the screen shot of my mail account
My gmail inbox where I received the mail from the user
As you can see there are two mails right now, the one which is unread it doesn't show the email id of the user rather shows me because the mail comes from the username provided in the recipient's address
I've done researches on it:
Used setFrom(new InternetAddress(email)) here email is the edittext input of the email by the sender.
went to many searches but none of the ideas are working here (couldn't provide the links as I don't have much reputations to post more than two links. I've two photos which is also in a link form as stackoverflow is not allowing me to uplaod it directly.)
Did this also setFrom(new InternetAddress("Sender"+"<"+email+">")) result is showing Sender
What I ended up doing is : setFrom(new InternetAddress(Config.EMAIL,email));
and got succeeded somehow in showing the email in the email address in the section. The picture will give you better idea
Mail when opened
but still result is same the inbox is repeatedly showing me the sender's email as mine.
Here's mycode:
1. SendMail.java
public class SendMail extends AsyncTask<Void,Void,Void> {
//Declaring Variables
private Context context;
private Session session;
//Information to send email
private String name;
private String email;
private String subject;
private String feedback;
private ProgressDialog progressDialog;
public SendMail(Context context,String name, String email,String subject, String feedback) {
this.context = context;
this.name = name;
this.email = email;
this.subject = subject;
this.feedback = feedback;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
//Showing progress dialog while sending email
progressDialog = ProgressDialog.show(context,"Sending feedback","Please wait...",false,false);
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
//Dismissing the progress dialog
progressDialog.dismiss();
//Showing a success message
Toast.makeText(context,"Feedback Sent", Toast.LENGTH_LONG).show();
}
#Override
protected Void doInBackground(Void... voids) {
//creating properties
Properties properties = new Properties();
//Configuring properties for gmail
//If you are not using gmail you may need to change the values
properties.put("mail.smtp.host", "smtp.gmail.com");
properties.put("mail.smtp.socketFactory.port", "465");
properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.put("mail.smtp.auth", "true");
properties.put("mail.smtp.port", "465");
//creating new session
session = Session.getDefaultInstance(properties, new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(Config.EMAIL, Config.PASSWORD);
}
});
InternetAddress fromAddress = null;
try {
fromAddress = new InternetAddress(Config.EMAIL,email);
}catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
//Creating MimeMessage object
MimeMessage mimeMessage = new MimeMessage(session);
//Setting sender address
mimeMessage.setFrom(fromAddress);
//Adding receiver
mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(Config.EMAIL));
//Adding subject
mimeMessage.setSubject(subject);
//Adding Message
mimeMessage.setText("Name:"+ " "+ name + "\n" + "Email:" + " " + email + "\n" +
"Feedback" + " " + feedback);
//Sending email
Transport.send(mimeMessage);
} catch (MessagingException e) {
Log.e("SendMail", e.getMessage(), e);
}
return null;
}
}
2.Config.java
public class Config {
public static final String EMAIL = "recipient_email#gmail.com";
public static final String PASSWORD ="password";
}
3. Feedback.java
private void sendEmail() {
//getting content from email
String subject = string.toString();
String email = inputEmail.getText().toString().trim();
String name = inputName.getText().toString().trim();
String feedback = inputFeedback.getText().toString().trim();
//Creating SendMail object
SendMail sendMail = new SendMail(getContext(),name,email,subject,feedback);
//Executing sendmail to send email
sendMail.execute();
}
Please suggest me some way so that I can reach up to my destination. Thanking you in advance.
If your application is using your credentials to login to Gmail, Gmail is not going to let you "fake" the From address to be some other user.
Also, you really don't want to embed your Gmail password in the application.
A much better approach is to create a web application that accepts the input for the feedback form and sends the email. The Android application can post the form data to the web application, which will compose the message and send it, adding the user's email address as another header field or as data in the body of the message. That makes sure your Gmail password is safe on your server, not in the application that users can access.
I can create group chat room successfully XMPP(smack). I have added
invitation listener, but never called. Does anyone know how to do it?
Using:
XMPP
Smack 4.2
Openfire server
Send Invitation code:
muc.invite(userId +"#" +XMPP.getInstance().HOST + "/Smack", "Meet me in this excellent room");
Invitation listener code:
MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);
manager.addInvitationListener(new InvitationListener() {
#Override
public void invitationReceived(XMPPConnection xmppConnection, MultiUserChat muc, String inviter, String reason, String password, Message message) {
try {
muc.join(nickname);
} catch (SmackException.NoResponseException e) {
e.printStackTrace();
} catch (XMPPException.XMPPErrorException e) {
e.printStackTrace();
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
}
});
Probably you have an issue about RESOURCE.
When you send an invitation to a certain JID, you might omit resource part or the message will be sent only to specified resource.
JID it's composed in following way:
user#serverdomain/resource
With this invitation, you are inviting only user using "Smack" as Resource.
Resource it's configurated in AbstractXMPPConnection object or in login phase
XMPPTCPConnectionConfiguration.builder()
.setServiceName(serverName)
.setHost(server)
.setPort(port)
.setResource( RESOURCE_IDENTIFIER)
.build();
connection = new XMPPTCPConnection(config);
connection.login(username, password, RESOURCE_IDENTIFIER);
So, probably, you declared as your resource identificator (just an arbitrary String) not "Smack" but "Spark" o something else or left default one.
Just omit Resource part (or fix with correct one, but I suggest to omit)
muc.invite(userId +"#" +XMPP.getInstance().HOST, "Meet me in this excellent room");
Of course, userId must exist and HOST it's the valid one
I have been trying to write an app that periodically parses the contents of gmail messages. I have been through the JavaMail FAQ and I have looked at a number of examples in the JavaMail download package but have been unable to get this to work. The code below currently causes the following gmail error:
Host is unresolved: imaps.gmail.com:993
I have also tried imap.gmail.com:143 but get:
Host is unresolved: imap.gmail.com:143
Any help or advice would be greatly appreciated. GMailReader is the class I am using to try and return gmail imap messages:
public class GMailReader extends javax.mail.Authenticator {
private String mailhost = "imaps.gmail.com";
private String user;
private String password;
private Session session;
public GMailReader(String user, String password) {
this.user = user;
this.password = password;
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "imaps");
props.setProperty("mail.imaps.host", mailhost);
props.put("mail.imaps.auth", "true");
props.put("mail.imaps.port", "993");
props.put("mail.imaps.socketFactory.port", "993");
props.put("mail.imaps.socketFactory.class",
"javax.net.ssl.SSLSocketFactory");
props.put("mail.imaps.socketFactory.fallback", "false");
props.setProperty("mail.imaps.quitwait", "false");
session = Session.getDefaultInstance(props, this);
}
public synchronized Message[] readMail() throws Exception {
try {
Store store = session.getStore("imaps");
store.connect("imaps.gmail.com", user, password);
Folder folder = store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);
Message[] msgs = folder.getMessages(1, 10);
FetchProfile fp = new FetchProfile();
fp.add(FetchProfile.Item.ENVELOPE);
folder.fetch(msgs, fp);
return msgs;
} catch (Exception e) {
Log.e("readMail", e.getMessage(), e);
return null;
}
}
}
I found an example here that was helpful. My error was the use of "mail.transport.protocol" rather than "mail.store.protocol."
hereafter a corrected version of
public class GMailReader extends javax.mail.Authenticator {
private static final String TAG = "GMailReader";
private String mailhost = "imap.gmail.com";
private Session session;
private Store store;
public GMailReader(String user, String password) {
Properties props = System.getProperties();
if (props == null){
Log.e(TAG, "Properties are null !!");
}else{
props.setProperty("mail.store.protocol", "imaps");
Log.d(TAG, "Transport: "+props.getProperty("mail.transport.protocol"));
Log.d(TAG, "Store: "+props.getProperty("mail.store.protocol"));
Log.d(TAG, "Host: "+props.getProperty("mail.imap.host"));
Log.d(TAG, "Authentication: "+props.getProperty("mail.imap.auth"));
Log.d(TAG, "Port: "+props.getProperty("mail.imap.port"));
}
try {
session = Session.getDefaultInstance(props, null);
store = session.getStore("imaps");
store.connect(mailhost, user, password);
Log.i(TAG, "Store: "+store.toString());
} catch (NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MessagingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized Message[] readMail() throws Exception {
try {
Folder folder = store.getFolder("Inbox");
folder.open(Folder.READ_ONLY);
/* TODO to rework
Message[] msgs = folder.getMessages(1, 10);
FetchProfile fp = new FetchProfile();
fp.add(FetchProfile.Item.ENVELOPE);
folder.fetch(msgs, fp);
*/
Message[] msgs = folder.getMessages();
return msgs;
} catch (Exception e) {
Log.e("readMail", e.getMessage(), e);
return null;
}
}
}
Bye
I see that the GmailReader concept very usefull and well designed in accordance whith the GmailSender example showed here:
Sending Email in Android using JavaMail API without using the default/built-in app
But Any news, on the error asked below ? And implementation of the proposition of JackN ?
Best Regards
SkN
After a huge amount of trial, error and googling , snakeman's edition of this answer provided the workable example I needed for a gmail reader;
However others should be aware (if using later versions of the Android SDK) of Manifest permission requirements and the need to use asyncTask to move potentially long-running tasks out of the main UI thread), both of which are mentioned in this SMTP example
I should also mention that if, like me, you intend to also implement an smtp sending class, I have seen somewhere a discussion suggesting that session.getInstance should be used in place of session.getDefaultInstance.