|
|
@ -20,12 +20,14 @@ package eu.faircode.email;
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
import android.app.Dialog;
|
|
|
|
import android.app.Dialog;
|
|
|
|
|
|
|
|
import android.content.ContentResolver;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.DialogInterface;
|
|
|
|
import android.content.DialogInterface;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.SharedPreferences;
|
|
|
|
import android.content.SharedPreferences;
|
|
|
|
import android.graphics.Color;
|
|
|
|
import android.graphics.Color;
|
|
|
|
import android.graphics.Rect;
|
|
|
|
import android.graphics.Rect;
|
|
|
|
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.text.TextUtils;
|
|
|
|
import android.text.TextUtils;
|
|
|
|
import android.view.LayoutInflater;
|
|
|
|
import android.view.LayoutInflater;
|
|
|
@ -59,13 +61,22 @@ import com.google.android.material.snackbar.Snackbar;
|
|
|
|
import org.json.JSONException;
|
|
|
|
import org.json.JSONException;
|
|
|
|
import org.json.JSONObject;
|
|
|
|
import org.json.JSONObject;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.io.BufferedOutputStream;
|
|
|
|
|
|
|
|
import java.io.FilterOutputStream;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.IOException;
|
|
|
|
|
|
|
|
import java.io.OutputStream;
|
|
|
|
import java.text.NumberFormat;
|
|
|
|
import java.text.NumberFormat;
|
|
|
|
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
import java.util.Calendar;
|
|
|
|
import java.util.Calendar;
|
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
import java.util.Locale;
|
|
|
|
|
|
|
|
import java.util.Properties;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import javax.mail.Message;
|
|
|
|
import javax.mail.MessagingException;
|
|
|
|
import javax.mail.MessagingException;
|
|
|
|
|
|
|
|
import javax.mail.Session;
|
|
|
|
|
|
|
|
import javax.mail.internet.InternetAddress;
|
|
|
|
|
|
|
|
|
|
|
|
import static android.app.Activity.RESULT_OK;
|
|
|
|
import static android.app.Activity.RESULT_OK;
|
|
|
|
|
|
|
|
|
|
|
@ -100,6 +111,7 @@ public class FragmentFolders extends FragmentBase {
|
|
|
|
static final int REQUEST_EMPTY_FOLDER = 2;
|
|
|
|
static final int REQUEST_EMPTY_FOLDER = 2;
|
|
|
|
static final int REQUEST_DELETE_FOLDER = 3;
|
|
|
|
static final int REQUEST_DELETE_FOLDER = 3;
|
|
|
|
static final int REQUEST_EXECUTE_RULES = 4;
|
|
|
|
static final int REQUEST_EXECUTE_RULES = 4;
|
|
|
|
|
|
|
|
static final int REQUEST_EXPORT_MESSAGES = 5;
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
|
@ -603,6 +615,10 @@ public class FragmentFolders extends FragmentBase {
|
|
|
|
if (resultCode == RESULT_OK && data != null)
|
|
|
|
if (resultCode == RESULT_OK && data != null)
|
|
|
|
onExecuteRules(data.getBundleExtra("args"));
|
|
|
|
onExecuteRules(data.getBundleExtra("args"));
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REQUEST_EXPORT_MESSAGES:
|
|
|
|
|
|
|
|
if (resultCode == RESULT_OK && data != null)
|
|
|
|
|
|
|
|
onExportMessages(data.getData());
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
Log.e(ex);
|
|
|
|
Log.e(ex);
|
|
|
@ -833,6 +849,91 @@ public class FragmentFolders extends FragmentBase {
|
|
|
|
}.execute(this, args, "folder:rules");
|
|
|
|
}.execute(this, args, "folder:rules");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void onExportMessages(Uri uri) {
|
|
|
|
|
|
|
|
long id = getArguments().getLong("selected_folder", -1L);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Bundle args = new Bundle();
|
|
|
|
|
|
|
|
args.putLong("id", id);
|
|
|
|
|
|
|
|
args.putParcelable("uri", uri);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
new SimpleTask<Void>() {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
protected void onPreExecute(Bundle args) {
|
|
|
|
|
|
|
|
ToastEx.makeText(getContext(), R.string.title_executing, Toast.LENGTH_LONG).show();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
protected void onPostExecute(Bundle args) {
|
|
|
|
|
|
|
|
ToastEx.makeText(getContext(), R.string.title_completed, Toast.LENGTH_LONG).show();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
protected Void onExecute(Context context, Bundle args) throws Throwable {
|
|
|
|
|
|
|
|
long fid = args.getLong("id");
|
|
|
|
|
|
|
|
Uri uri = args.getParcelable("uri");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!"content".equals(uri.getScheme())) {
|
|
|
|
|
|
|
|
Log.w("Export uri=" + uri);
|
|
|
|
|
|
|
|
throw new IllegalArgumentException(context.getString(R.string.title_no_stream));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DB db = DB.getInstance(context);
|
|
|
|
|
|
|
|
List<Long> ids = db.message().getMessageIdsByFolder(fid);
|
|
|
|
|
|
|
|
if (ids == null)
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
|
|
|
|
|
|
|
|
SimpleDateFormat df = new SimpleDateFormat(PATTERN_ASCTIME, Locale.US);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Properties props = MessageHelper.getSessionProperties();
|
|
|
|
|
|
|
|
Session isession = Session.getInstance(props, null);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// https://www.ietf.org/rfc/rfc4155.txt
|
|
|
|
|
|
|
|
// http://qmail.org./man/man5/mbox.html
|
|
|
|
|
|
|
|
ContentResolver resolver = context.getContentResolver();
|
|
|
|
|
|
|
|
try (OutputStream out = new BufferedOutputStream(resolver.openOutputStream(uri))) {
|
|
|
|
|
|
|
|
for (long id : ids) {
|
|
|
|
|
|
|
|
EntityMessage message = db.message().getMessage(id);
|
|
|
|
|
|
|
|
if (message == null)
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String email = null;
|
|
|
|
|
|
|
|
if (message.from != null && message.from.length > 0)
|
|
|
|
|
|
|
|
email = ((InternetAddress) message.from[0]).getAddress();
|
|
|
|
|
|
|
|
if (TextUtils.isEmpty(email))
|
|
|
|
|
|
|
|
email = "MAILER-DAEMON";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
out.write(("From " + email + " " + df.format(message.received) + "\n").getBytes());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Message imessage = MessageHelper.from(context, message, null, isession, false);
|
|
|
|
|
|
|
|
imessage.writeTo(new FilterOutputStream(out) {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public void write(int b) throws IOException {
|
|
|
|
|
|
|
|
super.write(b);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public void flush() throws IOException {
|
|
|
|
|
|
|
|
super.flush();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
out.write("\n".getBytes());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
protected void onException(Bundle args, Throwable ex) {
|
|
|
|
|
|
|
|
Log.unexpectedError(getParentFragmentManager(), ex);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}.execute(this, args, "folder:export");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static class FragmentDialogApply extends FragmentDialogBase {
|
|
|
|
public static class FragmentDialogApply extends FragmentDialogBase {
|
|
|
|
@NonNull
|
|
|
|
@NonNull
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|