package com.integreight.onesheeld.shields.controller; import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.AsyncTask; import android.os.Build; import android.util.Base64; import android.widget.Toast; import com.google.api.client.extensions.android.http.AndroidHttp; import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential; import com.google.api.client.googleapis.extensions.android.gms.auth.GooglePlayServicesAvailabilityIOException; import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException; import com.google.api.client.http.HttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.jackson2.JacksonFactory; import com.google.api.services.gmail.Gmail; import com.google.api.client.util.ExponentialBackOff; import com.google.api.services.gmail.GmailScopes; import com.google.api.services.gmail.model.Message; import com.integreight.onesheeld.R; import com.integreight.onesheeld.enums.UIShield; import com.integreight.onesheeld.sdk.ShieldFrame; import com.integreight.onesheeld.shields.ControllerParent; import com.integreight.onesheeld.shields.controller.utils.CameraUtils; import com.integreight.onesheeld.utils.ConnectionDetector; import com.integreight.onesheeld.utils.CrashlyticsUtils; import com.integreight.onesheeld.utils.Log; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Properties; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.FileDataSource; import javax.mail.BodyPart; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.Session; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; public class EmailShield extends ControllerParent<EmailShield> { private EmailEventHandler eventHandler; private static final byte SEND_METHOD_ID = (byte) 0x01; private static final byte SEND_WITH_ATTACHMENT = (byte) 0x02; private static SharedPreferences mSharedPreferences; private static final String PREF_EMAIL_SHIELD_USER_LOGIN = "user_login_status"; private static final String PREF_EMAIL_SHIELD_GMAIL_ACCOUNT = "gmail_account"; private static final int PREF_EMAIL_SHIELD_REQUEST_AUTHORIZATION = 1001; private static int ORDER_GET_LABELS = 0; private static int ORDER_SEND_EMAIL = 1; private String userEmail = ""; private static String message_body = ""; private static String message_reciption = ""; private static String message_subject = ""; private static String attachment_file_path = null; private static DataSource source; private static BodyPart messageFilePart,messageBodyPart; private volatile boolean isSending = false; private GoogleAccountCredential mCredential; private static final String[] SCOPES = {GmailScopes.GMAIL_COMPOSE}; private Boolean isLoggedIn = false; private Queue<EmailShield.EmailRequest> emailsQueue = new ConcurrentLinkedQueue<>(); ///// public EmailShield() { super(); } @Override public ControllerParent<EmailShield> init(String tag) { mSharedPreferences = activity.getApplicationContext() .getSharedPreferences("com.integreight.onesheeld", Context.MODE_PRIVATE); mCredential = GoogleAccountCredential.usingOAuth2( activity.getApplicationContext(), Arrays.asList(SCOPES)) .setBackOff(new ExponentialBackOff()) .setSelectedAccountName(mSharedPreferences.getString(PREF_EMAIL_SHIELD_GMAIL_ACCOUNT, null)); return super.init(tag); } public EmailShield(Activity activity, String tag) { super(activity, tag); } public void setEmailEventHandler(EmailEventHandler eventHandler) { this.eventHandler = eventHandler; } public boolean isSending(){ return isSending; } public void setCredential(String accountName){ setAccountName(accountName); mCredential = GoogleAccountCredential.usingOAuth2( activity.getApplicationContext(), Arrays.asList(SCOPES)) .setBackOff(new ExponentialBackOff()) .setSelectedAccountName(mSharedPreferences.getString(PREF_EMAIL_SHIELD_GMAIL_ACCOUNT, null)); } public void logout(){ SharedPreferences.Editor editor = mSharedPreferences.edit(); editor.remove(PREF_EMAIL_SHIELD_GMAIL_ACCOUNT); editor.remove(PREF_EMAIL_SHIELD_USER_LOGIN); editor.commit(); mCredential = GoogleAccountCredential.usingOAuth2( activity.getApplicationContext(), Arrays.asList(SCOPES)) .setBackOff(new ExponentialBackOff()) .setSelectedAccountName(mSharedPreferences.getString(PREF_EMAIL_SHIELD_GMAIL_ACCOUNT, null)); } public GoogleAccountCredential getCredential(){ return mCredential; } public String getUserEmail(){ return mSharedPreferences.getString(PREF_EMAIL_SHIELD_GMAIL_ACCOUNT, ""); } public static interface EmailEventHandler { void onEmailsent(String email_send_to, String subject); void onSendingAuthError(String error,Intent intent,int requestCode); void onSuccess(); void onEmailnotSent(String message_not_sent); void startProgress(); void stopProgress(); // GoogleAccountCredential getCredential(); } @Override public void onNewShieldFrameReceived(ShieldFrame frame) { // TODO Auto-generated method stub if (frame.getShieldId() == UIShield.EMAIL_SHIELD.getId()) { if (frame.getFunctionId() == SEND_METHOD_ID || frame.getFunctionId() == SEND_WITH_ATTACHMENT) { if (isLoggedIn()) { // retrieve user name and password from sharedPref... setUserData(); // send Email String email_send_to = frame.getArgumentAsString(0); String subject = frame.getArgumentAsString(1); String body = frame.getArgumentAsString(2); // check Internet connection if (ConnectionDetector .isConnectingToInternet(getApplication() .getApplicationContext())) { if (frame.getFunctionId() == SEND_METHOD_ID) { // sendGmail(email_send_to, subject, body, null); EmailRequest request=new EmailRequest(email_send_to,subject,body,null); if (emailsQueue == null) emailsQueue = new ConcurrentLinkedQueue<>(); emailsQueue.add(request); checkQueue(); } else if (frame.getFunctionId() == SEND_WITH_ATTACHMENT) { byte sourceFolderId = frame.getArgument(3)[0]; String imgPath = null; if (sourceFolderId == CameraUtils.FROM_ONESHEELD_FOLDER) imgPath = CameraUtils .getLastCapturedImagePathFromOneSheeldFolder(activity,true); else if (sourceFolderId == CameraUtils.FROM_CAMERA_FOLDER) imgPath = CameraUtils .getLastCapturedImagePathFromCameraFolder(activity); EmailRequest request=new EmailRequest(email_send_to,subject,body,imgPath); if (emailsQueue == null) emailsQueue = new ConcurrentLinkedQueue<>(); emailsQueue.add(request); checkQueue(); // sendGmail(email_send_to, subject, body, imgPath); } } else Toast.makeText( getApplication().getApplicationContext(), R.string.general_toasts_please_check_your_internet_connection_and_try_again_toast, Toast.LENGTH_SHORT).show(); } } } } private void sendGmail(String email_send_to, String subject, String body, String filePath) { message_body = body; message_reciption = email_send_to; message_subject = subject; attachment_file_path = filePath; new sendGmailinBackground(mCredential,ORDER_SEND_EMAIL).execute(); } public void sendTestRequest(GoogleAccountCredential credential){ if (ConnectionDetector.isConnectingToInternet(getApplication().getApplicationContext())) { new sendGmailinBackground(credential, ORDER_GET_LABELS).execute(); } } public class sendGmailinBackground extends AsyncTask<Void, Void, String> { private com.google.api.services.gmail.Gmail mService = null; private Exception mLastError = null; private int order = 0; public sendGmailinBackground(GoogleAccountCredential credential,int order){ isSending=true; HttpTransport transport = AndroidHttp.newCompatibleTransport(); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); mService = new Gmail.Builder( transport, jsonFactory, credential) .setApplicationName(getActivity().getString(R.string.app_name)) .build(); this.order = order; Log.d("Email","Sending Created!"); } @Override protected String doInBackground(Void... params) { Log.d("Email","Sending Started!"); if (eventHandler != null) eventHandler.startProgress(); try { return sendEmail(); } catch (Exception e) { mLastError = e; cancel(true); if (eventHandler != null) eventHandler.stopProgress(); return null; } } @Override protected void onPostExecute(String result) { // TODO Auto-generated method stub super.onPostExecute(result); if (result != null){ if (eventHandler != null) eventHandler.onSuccess(); } attachment_file_path = null; if (eventHandler != null) eventHandler.stopProgress(); isSending=false; Log.d("Email","Sending Ended!"); if (emailsQueue != null && !emailsQueue.isEmpty()) emailsQueue.poll(); checkQueue(); } @Override protected void onCancelled(String s) { //super.onCancelled(); if (mLastError != null) { if (mLastError instanceof GooglePlayServicesAvailabilityIOException) { //showGooglePlayServicesAvailabilityErrorDialog(((GooglePlayServicesAvailabilityIOException) mLastError).getConnectionStatusCode()); if (eventHandler != null && order == ORDER_SEND_EMAIL) { Log.d("Email","The following google play service error occurred:\n" + ((GooglePlayServicesAvailabilityIOException) mLastError).getConnectionStatusCode()); eventHandler.onEmailnotSent(activity.getString(R.string.email_email_couldnt_be_sent_toast)); } if(order>0)CrashlyticsUtils.logException(mLastError); } else if (mLastError instanceof UserRecoverableAuthIOException) { if (eventHandler != null) eventHandler.onSendingAuthError(mLastError.getMessage(),((UserRecoverableAuthIOException) mLastError).getIntent(),PREF_EMAIL_SHIELD_REQUEST_AUTHORIZATION); } else { if (eventHandler != null && order == ORDER_SEND_EMAIL) { Log.d("Email", "The following error occurred:\n" + mLastError.getMessage()); eventHandler.onEmailnotSent(activity.getString(R.string.email_email_couldnt_be_sent_toast)); } if(order>0)CrashlyticsUtils.logException(mLastError); } } else { if (eventHandler != null) eventHandler.onEmailnotSent(activity.getString(R.string.email_email_couldnt_be_sent_toast)); } if (eventHandler != null) eventHandler.stopProgress(); isSending=false; Log.d("Email","Sending Canceled!"); checkQueue(); } File attachedFile; private String sendEmail() throws IOException { try { if (attachment_file_path != null) attachedFile = new File(attachment_file_path); if (order > 0) { if (attachment_file_path == null) { mService.users().messages().send("me", createMessageWithEmail(createEmail(message_reciption, userEmail, message_subject, message_body))).execute(); }else { if (attachedFile.exists()) mService.users().messages().send("me", createMessageWithEmail(createEmailWithAttachment(message_reciption, userEmail, message_subject, message_body, attachment_file_path))).execute(); else { mService.users().messages().send("me", createMessageWithEmail(createEmail(message_reciption, userEmail, message_subject, message_body))).execute(); // cancel(true); // if (eventHandler != null) // eventHandler.stopProgress(); return ""; } } }else mService.users().labels().list("me").execute(); } catch (MessagingException e) { e.printStackTrace(); return null; } return ""; } } private void setUserData() { this.userEmail = mSharedPreferences.getString( PREF_EMAIL_SHIELD_GMAIL_ACCOUNT, ""); } public void setAccountName(String accountName){ SharedPreferences.Editor editor = mSharedPreferences.edit(); editor.putString(PREF_EMAIL_SHIELD_GMAIL_ACCOUNT, accountName); editor.commit(); } public void setLoggedIn(){ SharedPreferences.Editor editor = mSharedPreferences.edit(); editor.putBoolean(PREF_EMAIL_SHIELD_USER_LOGIN, true); editor.commit(); } public boolean isLoggedIn() { return mSharedPreferences.getBoolean(PREF_EMAIL_SHIELD_USER_LOGIN,false); } @Override public void reset() { // TODO Auto-generated method stub emailsQueue = new ConcurrentLinkedQueue<>(); isSending=false; } public static MimeMessage createEmail(String to, String from, String subject, String bodyText) throws MessagingException{ Properties props = new Properties(); Session session = Session.getDefaultInstance(props, null); MimeMessage email = new MimeMessage(session); InternetAddress tAddress = new InternetAddress(to); InternetAddress fAddress = new InternetAddress(from); email.setFrom(fAddress); email.addRecipient(javax.mail.Message.RecipientType.TO, tAddress); email.setSubject(subject); email.setText(bodyText); return email; } public static MimeMessage createEmailWithAttachment(String to, String from, String subject, String bodyText,String filePath) throws MessagingException{ File file = new File(filePath); Properties props = new Properties(); Session session = Session.getDefaultInstance(props, null); MimeMessage email = new MimeMessage(session); Multipart multipart = new MimeMultipart(); InternetAddress tAddress = new InternetAddress(to); InternetAddress fAddress = new InternetAddress(from); email.setFrom(fAddress); email.addRecipient(javax.mail.Message.RecipientType.TO, tAddress); email.setSubject(subject); if (file.exists()) { source = new FileDataSource(filePath); messageFilePart = new MimeBodyPart(); messageBodyPart = new MimeBodyPart(); try { messageBodyPart.setText(bodyText); messageFilePart.setDataHandler(new DataHandler(source)); messageFilePart.setFileName(file.getName()); multipart.addBodyPart(messageBodyPart); multipart.addBodyPart(messageFilePart); email.setContent(multipart); } catch (MessagingException e) { e.printStackTrace(); } }else email.setText(bodyText); return email; } public static Message createMessageWithEmail(MimeMessage email) throws MessagingException, IOException { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); email.writeTo(bytes); String encodedEmail = Base64.encodeToString(bytes.toByteArray(), Base64.URL_SAFE); Message message = new Message(); message.setRaw(encodedEmail); return message; } @Override public ControllerParent<EmailShield> invalidate( com.integreight.onesheeld.shields.ControllerParent.SelectionAction selectionAction, boolean isToastable) { this.selectionAction = selectionAction; addRequiredPremission(Manifest.permission.GET_ACCOUNTS); if(Build.VERSION.SDK_INT >=16) addRequiredPremission(Manifest.permission.READ_EXTERNAL_STORAGE); if (checkForPermissions()) this.selectionAction.onSuccess(); else this.selectionAction.onFailure(); return super.invalidate(selectionAction, isToastable); } private synchronized void checkQueue() { if (emailsQueue != null && !emailsQueue.isEmpty() && !isSending) { EmailRequest request = emailsQueue.peek(); if(!request.canRetry()) request = emailsQueue.poll(); request.decrementRetries(); if (eventHandler != null) eventHandler.onEmailsent(request.getAddress(), request.getSubject()); isSending=true; if (request.getImagePath()!=null) { sendGmail(request.getAddress(), request.getSubject(), request.getBody(), request.getImagePath()); } else { sendGmail(request.getAddress(), request.getSubject(), request.getBody(), null); } Log.d("Email","Sending Requested!"); } } public class EmailRequest{ private String address; private String subject; private String body; private String imagePath; private int retries; public EmailRequest(String address, String subject, String body, String imagePath) { this.address=address; this.subject=subject; this.body=body; this.imagePath=imagePath; retries=3; } public boolean canRetry() { return retries>0; } public void decrementRetries() { if(retries>0)retries--; } public String getAddress() { return address; } public String getSubject() { return subject; } public String getBody() { return body; } public String getImagePath() { return imagePath; } } }