diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 8cf563738..7d837645a 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -72,6 +72,22 @@
android:label="@string/choose_folder_title"
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/message_compose.xml b/res/layout/message_compose.xml
index acb7f4363..23305dfa0 100644
--- a/res/layout/message_compose.xml
+++ b/res/layout/message_compose.xml
@@ -11,6 +11,15 @@
+
+
+
+ android:capitalize="sentences"
+ android:hint="@string/message_compose_content_hint" />
+
+
@@ -86,9 +107,26 @@
android:layout_centerVertical="true"
android:layout_alignParentRight="true" />
-
+ android:layout_weight="1.0"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:gravity="left|top"
+ android:minLines="3" android:autoText="true"
+ android:capitalize="sentences" />
+
diff --git a/res/menu/manage_identities_context.xml b/res/menu/manage_identities_context.xml
new file mode 100644
index 000000000..bb031468a
--- /dev/null
+++ b/res/menu/manage_identities_context.xml
@@ -0,0 +1,13 @@
+
+
diff --git a/res/menu/manage_identities_option.xml b/res/menu/manage_identities_option.xml
new file mode 100644
index 000000000..82922ddc0
--- /dev/null
+++ b/res/menu/manage_identities_option.xml
@@ -0,0 +1,9 @@
+
+
diff --git a/res/menu/message_compose_option.xml b/res/menu/message_compose_option.xml
index 9b13bceec..0b86f5155 100644
--- a/res/menu/message_compose_option.xml
+++ b/res/menu/message_compose_option.xml
@@ -30,4 +30,10 @@
android:title="@string/discard_action"
android:icon="@drawable/ic_menu_close_clear_cancel"
/>
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3c4b65721..31d562bc7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -185,8 +185,9 @@ Welcome to K-9 Mail setup. K-9 is an open source email client for Android based
Cc
Bcc
Subject
- \n\n-------- Original Message --------\nSubject: %s\nFrom: %s\nTo: %s\nCC: %s\n\n
- \n\n%s wrote:\n\n
+ Message text
+ \n-------- Original Message --------\nSubject: %s\nFrom: %s\nTo: %s\nCC: %s\n\n
+ \n%s wrote:\n\n
Quoted text
You must add at least one recipient.
Some attachments were not downloaded. They will be downloaded automatically before this message is sent.
@@ -194,6 +195,7 @@ Welcome to K-9 Mail setup. K-9 is an open source email client for Android based
To:%s
+ From: %s <%s>
To:
Open
Save
@@ -411,14 +413,46 @@ Welcome to K-9 Mail setup. K-9 is an open source email client for Android based
Message composition options
Composing messages
+ Manage identities
+
+ Manage identities
+
+ Manage identity
+
+ Edit identities
+ Create new identity
Bcc all messages to
Send this address a copy of every outgoing message
+ Edit
+ Move up
+ Move down
+ Move to top / make default
+ Remove
+ Identity description
+ (Optional)
+ Your name
+ (Optional)
+ Email address
+ (Required)
+ Signature
+ (Optional)
+
Signature
Append a signature to every message you send
+ --\nSent from my Android phone with K-9. Please excuse my brevity.
+ Initial identity
+ Choose identity
+ Choose identity
+
+ Go to Account Settings -> Manage Identities to create identities
+ Cannot remove only identity
+ Cannot choose an identity which has no email address
+ Identity choice and signature edits will not be saved with a draft
+
Earliest messages first
Latest messages first
Sender alphabetical
diff --git a/res/xml/account_settings_preferences.xml b/res/xml/account_settings_preferences.xml
index 9affb8db5..812911331 100644
--- a/res/xml/account_settings_preferences.xml
+++ b/res/xml/account_settings_preferences.xml
@@ -98,6 +98,10 @@
android:key="composition"
android:title="@string/account_settings_composition_label" />
+
+
diff --git a/src/com/android/email/Account.java b/src/com/android/email/Account.java
index d3dfcc308..2660729e8 100644
--- a/src/com/android/email/Account.java
+++ b/src/com/android/email/Account.java
@@ -2,7 +2,9 @@
package com.android.email;
import java.io.Serializable;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.UUID;
import com.android.email.mail.Address;
@@ -35,9 +37,6 @@ public class Account implements Serializable {
String mLocalStoreUri;
String mTransportUri;
String mDescription;
- String mName;
- String mEmail;
- String mSignature;
String mAlwaysBcc;
int mAutomaticCheckIntervalMinutes;
int mDisplayCount;
@@ -57,6 +56,7 @@ public class Account implements Serializable {
boolean mNotifySync;
HideButtons mHideMessageViewButtons;
boolean mIsSignatureBeforeQuotedText;
+ List identities;
public enum FolderMode {
ALL, FIRST_CLASS, FIRST_AND_SECOND_CLASS, NOT_SECOND_CLASS;
@@ -84,7 +84,6 @@ public class Account implements Serializable {
mAccountNumber = -1;
mNotifyNewMail = true;
mNotifySync = true;
- mSignature = "Sent from my Android phone with K-9. Please excuse my brevity.";
mVibrate = false;
mFolderDisplayMode = FolderMode.NOT_SECOND_CLASS;
mFolderSyncMode = FolderMode.FIRST_CLASS;
@@ -92,6 +91,57 @@ public class Account implements Serializable {
mHideMessageViewButtons = HideButtons.NEVER;
mRingtoneUri = "content://settings/system/notification_sound";
mIsSignatureBeforeQuotedText = false;
+
+ identities = new ArrayList();
+
+ Identity identity = new Identity();
+ identity.setSignature(context.getString(R.string.default_signature));
+ identity.setDescription(context.getString(R.string.default_identity_description));
+ identities.add(identity);
+ }
+
+ public class Identity implements Serializable
+ {
+ String mDescription;
+ String mName;
+ String mEmail;
+ String mSignature;
+ public String getName()
+ {
+ return mName;
+ }
+ public void setName(String name)
+ {
+ mName = name;
+ }
+ public String getEmail()
+ {
+ return mEmail;
+ }
+ public void setEmail(String email)
+ {
+ mEmail = email;
+ }
+ public String getSignature()
+ {
+ return mSignature;
+ }
+ public void setSignature(String signature)
+ {
+ mSignature = signature;
+ }
+ public String getDescription()
+ {
+ return mDescription;
+ }
+ public void setDescription(String description)
+ {
+ mDescription = description;
+ }
+ public String toString()
+ {
+ return "Account.Identity(description=" + mDescription + ", name=" + mName + ", email=" + mEmail + ", signature=" + mSignature;
+ }
}
Account(Preferences preferences, String uuid) {
@@ -110,9 +160,6 @@ public class Account implements Serializable {
+ ".transportUri", null));
mDescription = preferences.getPreferences().getString(mUuid + ".description", null);
mAlwaysBcc = preferences.getPreferences().getString(mUuid + ".alwaysBcc", mAlwaysBcc);
- mName = preferences.getPreferences().getString(mUuid + ".name", mName);
- mEmail = preferences.getPreferences().getString(mUuid + ".email", mEmail);
- mSignature = preferences.getPreferences().getString(mUuid + ".signature", mSignature);
mAutomaticCheckIntervalMinutes = preferences.getPreferences().getInt(mUuid
+ ".automaticCheckIntervalMinutes", -1);
mDisplayCount = preferences.getPreferences().getInt(mUuid + ".displayCount", -1);
@@ -202,6 +249,93 @@ public class Account implements Serializable {
}
mIsSignatureBeforeQuotedText = preferences.getPreferences().getBoolean(mUuid + ".signatureBeforeQuotedText", false);
+ identities = loadIdentities(preferences.getPreferences());
+ }
+
+ private List loadIdentities(SharedPreferences prefs)
+ {
+ List newIdentities = new ArrayList();
+ int ident = 0;
+ boolean gotOne = false;
+ do
+ {
+ gotOne = false;
+ String name = prefs.getString(mUuid + ".name." + ident, null);
+ String email = prefs.getString(mUuid + ".email." + ident, null);
+ String signature = prefs.getString(mUuid + ".signature." + ident, null);
+ String description = prefs.getString(mUuid + ".description." + ident, null);
+ if (email != null)
+ {
+ Identity identity = new Identity();
+ identity.setName(name);
+ identity.setEmail(email);
+ identity.setSignature(signature);
+ identity.setDescription(description);
+ newIdentities.add(identity);
+ gotOne = true;
+ }
+ ident++;
+ } while (gotOne);
+
+ if (newIdentities.size() == 0)
+ {
+ String name = prefs.getString(mUuid + ".name", null);
+ String email = prefs.getString(mUuid + ".email", null);
+ String signature = prefs.getString(mUuid + ".signature", null);
+ Identity identity = new Identity();
+ identity.setName(name);
+ identity.setEmail(email);
+ identity.setSignature(signature);
+ identity.setDescription(email);
+ newIdentities.add(identity);
+ }
+
+ return newIdentities;
+ }
+
+ private void deleteIdentities(SharedPreferences prefs, SharedPreferences.Editor editor)
+ {
+ int ident = 0;
+ boolean gotOne = false;
+ do
+ {
+ gotOne = false;
+ String email = prefs.getString(mUuid + ".email." + ident, null);
+ if (email != null)
+ {
+ editor.remove(mUuid + ".name." + ident);
+ editor.remove(mUuid + ".email." + ident);
+ editor.remove(mUuid + ".signature." + ident);
+ editor.remove(mUuid + ".description." + ident);
+ gotOne = true;
+ }
+ ident++;
+ } while (gotOne);
+ }
+
+ private void saveIdentities(SharedPreferences prefs, SharedPreferences.Editor editor)
+ {
+ deleteIdentities(prefs, editor);
+ int ident = 0;
+
+ for (Identity identity : identities)
+ {
+ editor.putString(mUuid + ".name." + ident, identity.getName());
+ editor.putString(mUuid + ".email." + ident, identity.getEmail());
+ editor.putString(mUuid + ".signature." + ident, identity.getSignature());
+ editor.putString(mUuid + ".description." + ident, identity.getDescription());
+ ident++;
+ }
+ }
+
+ public List getIdentities()
+ {
+ return identities;
+ }
+
+ public void setIdentities(List newIdentities)
+ {
+ identities = newIdentities;
}
public String getUuid() {
@@ -233,27 +367,27 @@ public class Account implements Serializable {
}
public String getName() {
- return mName;
+ return identities.get(0).getName();
}
public void setName(String name) {
- this.mName = name;
+ identities.get(0).setName(name);
}
public String getSignature() {
- return mSignature;
+ return identities.get(0).getSignature();
}
public void setSignature(String signature) {
- this.mSignature = signature;
+ identities.get(0).setSignature(signature);
}
public String getEmail() {
- return mEmail;
+ return identities.get(0).getEmail();
}
public void setEmail(String email) {
- this.mEmail = email;
+ identities.get(0).setEmail(email);
}
public String getAlwaysBcc() {
@@ -264,6 +398,14 @@ public class Account implements Serializable {
this.mAlwaysBcc = alwaysBcc;
}
+ public Identity getIdentity(int i)
+ {
+ if (i < identities.size())
+ {
+ return identities.get(i);
+ }
+ return null;
+ }
public boolean isVibrate() {
return mVibrate;
@@ -321,6 +463,7 @@ public class Account implements Serializable {
editor.remove(mUuid + ".folderTargetMode");
editor.remove(mUuid + ".hideButtonsEnum");
editor.remove(mUuid + ".signatureBeforeQuotedText");
+ deleteIdentities(preferences.getPreferences(), editor);
editor.commit();
}
@@ -362,9 +505,6 @@ public class Account implements Serializable {
editor.putString(mUuid + ".localStoreUri", mLocalStoreUri);
editor.putString(mUuid + ".transportUri", Utility.base64Encode(mTransportUri));
editor.putString(mUuid + ".description", mDescription);
- editor.putString(mUuid + ".name", mName);
- editor.putString(mUuid + ".email", mEmail);
- editor.putString(mUuid + ".signature", mSignature);
editor.putString(mUuid + ".alwaysBcc", mAlwaysBcc);
editor.putInt(mUuid + ".automaticCheckIntervalMinutes", mAutomaticCheckIntervalMinutes);
editor.putInt(mUuid + ".displayCount", mDisplayCount);
@@ -386,6 +526,8 @@ public class Account implements Serializable {
editor.putString(mUuid + ".folderTargetMode", mFolderTargetMode.name());
editor.putBoolean(mUuid + ".signatureBeforeQuotedText", this.mIsSignatureBeforeQuotedText);
+ saveIdentities(preferences.getPreferences(), editor);
+
editor.commit();
}
@@ -455,10 +597,17 @@ public class Account implements Serializable {
}
- // TODO: When there are multiple identities, this method should try all of them
public boolean isAnIdentity(Address addr)
{
- return getEmail().equals(addr.getAddress());
+ for (Identity identity : identities)
+ {
+ String email = identity.getEmail();
+ if (email != null && email.equalsIgnoreCase(addr.getAddress()))
+ {
+ return true;
+ }
+ }
+ return false;
}
public int getDisplayCount() {
diff --git a/src/com/android/email/Email.java b/src/com/android/email/Email.java
index 813641770..bb82f8fb1 100644
--- a/src/com/android/email/Email.java
+++ b/src/com/android/email/Email.java
@@ -99,14 +99,12 @@ public class Email extends Application {
*/
public static final String FOLDER_NONE = "-NONE-";
+ public static final String LOCAL_UID_PREFIX = "K9LOCAL:";
- // The next time the LocalStore.java DB_VERSION is incremented, please delete the current
- // LOCAL_UID_PREFIX and this comment, and uncomment the K9LOCAL: version of this static string
- public static final String LOCAL_UID_PREFIX = "Local";
- //public static final String LOCAL_UID_PREFIX = "K9LOCAL:";
-
public static final String REMOTE_UID_PREFIX = "K9REMOTE:";
+ public static final String K9MAIL_IDENTITY = "X-K9mail-Identity";
+
/**
* Specifies how many messages will be shown in a folder by default. This number is set
* on each new folder and can be incremented with "Load more messages..." by the
diff --git a/src/com/android/email/activity/ChooseIdentity.java b/src/com/android/email/activity/ChooseIdentity.java
new file mode 100644
index 000000000..ac0362937
--- /dev/null
+++ b/src/com/android/email/activity/ChooseIdentity.java
@@ -0,0 +1,138 @@
+
+package com.android.email.activity;
+
+import java.util.List;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.View;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.Toast;
+
+import com.android.email.Account;
+import com.android.email.Preferences;
+import com.android.email.R;
+
+public class ChooseIdentity extends ListActivity
+{
+ Account mAccount;
+ String mUID;
+ ArrayAdapter adapter;
+ private ChooseIdentityHandler mHandler = new ChooseIdentityHandler();
+
+ public static final String EXTRA_ACCOUNT = "com.android.email.ChooseIdentity_account";
+ public static final String EXTRA_IDENTITY = "com.android.email.ChooseIdentity_identity";
+
+ protected List identities = null;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+
+ getListView().setTextFilterEnabled(true);
+ getListView().setItemsCanFocus(false);
+ getListView().setChoiceMode(ListView.CHOICE_MODE_NONE);
+ Intent intent = getIntent();
+ mAccount = (Account) intent.getSerializableExtra(EXTRA_ACCOUNT);
+
+ adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1);
+
+ setListAdapter(adapter);
+ setupClickListeners();
+ }
+
+
+ @Override
+ public void onResume()
+ {
+ super.onResume();
+ refreshView();
+ }
+
+
+ protected void refreshView()
+ {
+ adapter.clear();
+
+ identities = mAccount.getIdentities();
+ for (Account.Identity identity : identities)
+ {
+ String email = identity.getEmail();
+ String description = identity.getDescription();
+ if (description == null || description.trim().length() == 0)
+ {
+ description = getString(R.string.message_view_from_format, identity.getName(), identity.getEmail());
+ }
+ adapter.add(description);
+ }
+
+ }
+
+ protected void setupClickListeners()
+ {
+ this.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener()
+ {
+ public void onItemClick(AdapterView adapterview, View view, int i, long l)
+ {
+ Account.Identity identity = mAccount.getIdentity(i);
+ String email = identity.getEmail();
+ if (email != null && email.trim().equals("") == false)
+ {
+ Intent intent = new Intent();
+
+ intent.putExtra(EXTRA_IDENTITY, mAccount.getIdentity(i));
+ setResult(RESULT_OK, intent);
+ finish();
+ }
+ else
+ {
+ Toast.makeText(ChooseIdentity.this, getString(R.string.identity_has_no_email),
+ Toast.LENGTH_LONG).show();
+ }
+ }
+ });
+
+ }
+
+ class ChooseIdentityHandler extends Handler
+ {
+
+ private static final int MSG_PROGRESS = 2;
+ private static final int MSG_DATA_CHANGED = 3;
+
+ public void handleMessage(android.os.Message msg)
+ {
+ switch (msg.what)
+ {
+ case MSG_PROGRESS:
+ setProgressBarIndeterminateVisibility(msg.arg1 != 0);
+ break;
+ case MSG_DATA_CHANGED:
+ adapter.notifyDataSetChanged();
+ break;
+ }
+ }
+
+ public void progress(boolean progress)
+ {
+ android.os.Message msg = new android.os.Message();
+ msg.what = MSG_PROGRESS;
+ msg.arg1 = progress ? 1 : 0;
+ sendMessage(msg);
+ }
+
+ public void dataChanged()
+ {
+ sendEmptyMessage(MSG_DATA_CHANGED);
+ }
+ }
+
+}
diff --git a/src/com/android/email/activity/EditIdentity.java b/src/com/android/email/activity/EditIdentity.java
new file mode 100644
index 000000000..c40c44dbd
--- /dev/null
+++ b/src/com/android/email/activity/EditIdentity.java
@@ -0,0 +1,120 @@
+package com.android.email.activity;
+
+import java.util.List;
+
+import com.android.email.Account;
+import com.android.email.Preferences;
+import com.android.email.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.widget.EditText;
+
+public class EditIdentity extends Activity
+{
+
+ public static final String EXTRA_IDENTITY = "com.android.email.EditIdentity_identity";
+ public static final String EXTRA_IDENTITY_INDEX = "com.android.email.EditIdentity_identity_index";
+ public static final String EXTRA_ACCOUNT = "com.android.email.EditIdentity_account";
+
+ private Account mAccount;
+ private Account.Identity mIdentity;
+ private int mIdentityIndex;
+ private EditText mDescriptionView;
+ private EditText mSignatureView;
+ private EditText mEmailView;
+// private EditText mAlwaysBccView;
+ private EditText mNameView;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ mIdentity = (Account.Identity)getIntent().getSerializableExtra(EXTRA_IDENTITY);
+ mIdentityIndex = getIntent().getIntExtra(EXTRA_IDENTITY_INDEX, -1);
+ mAccount = (Account) getIntent().getSerializableExtra(EXTRA_ACCOUNT);
+
+ if (mIdentityIndex == -1)
+ {
+ mIdentity = mAccount.new Identity();
+ }
+
+ setContentView(R.layout.edit_identity);
+
+ /*
+ * If we're being reloaded we override the original account with the one
+ * we saved
+ */
+ if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_IDENTITY))
+ {
+ mIdentity = (Account.Identity)savedInstanceState.getSerializable(EXTRA_IDENTITY);
+ }
+
+ mDescriptionView = (EditText)findViewById(R.id.description);
+ mDescriptionView.setText(mIdentity.getDescription());
+
+ mNameView = (EditText)findViewById(R.id.name);
+ mNameView.setText(mIdentity.getName());
+
+ mEmailView = (EditText)findViewById(R.id.email);
+ mEmailView.setText(mIdentity.getEmail());
+
+// mAccountAlwaysBcc = (EditText)findViewById(R.id.bcc);
+// mAccountAlwaysBcc.setText(mIdentity.getAlwaysBcc());
+
+ mSignatureView = (EditText)findViewById(R.id.signature);
+ mSignatureView.setText(mIdentity.getSignature());
+ }
+
+ @Override
+ public void onResume()
+ {
+ super.onResume();
+ }
+
+ private void saveIdentity()
+ {
+
+ mIdentity.setDescription(mDescriptionView.getText().toString());
+ mIdentity.setEmail(mEmailView.getText().toString());
+ // mIdentity.setAlwaysBcc(mAccountAlwaysBcc.getText().toString());
+ mIdentity.setName(mNameView.getText().toString());
+ mIdentity.setSignature(mSignatureView.getText().toString());
+
+ List identities = mAccount.getIdentities();
+ if (mIdentityIndex == -1)
+ {
+ identities.add(mIdentity);
+ }
+ else
+ {
+ identities.remove(mIdentityIndex);
+ identities.add(mIdentityIndex, mIdentity);
+ }
+
+ mAccount.save(Preferences.getPreferences(getApplication().getApplicationContext()));
+
+ finish();
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event)
+ {
+ if (keyCode == KeyEvent.KEYCODE_BACK)
+ {
+ saveIdentity();
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState)
+ {
+ super.onSaveInstanceState(outState);
+ outState.putSerializable(EXTRA_IDENTITY, mIdentity);
+ }
+}
diff --git a/src/com/android/email/activity/ManageIdentities.java b/src/com/android/email/activity/ManageIdentities.java
new file mode 100644
index 000000000..f90cfee0b
--- /dev/null
+++ b/src/com/android/email/activity/ManageIdentities.java
@@ -0,0 +1,161 @@
+package com.android.email.activity;
+
+import android.content.Intent;
+import android.view.ContextMenu;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.Toast;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+
+import com.android.email.Account;
+import com.android.email.Preferences;
+import com.android.email.R;
+
+public class ManageIdentities extends ChooseIdentity
+{
+ private boolean mIdentitiesChanged = false;
+ public static final String EXTRA_IDENTITIES = "com.android.email.EditIdentity_identities";
+
+ private static final int ACTIVITY_EDIT_IDENTITY = 1;
+ protected void setupClickListeners()
+ {
+ this.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener()
+ {
+ public void onItemClick(AdapterView adapterview, View view, int i, long l)
+ {
+ editItem(i);
+ }
+ });
+
+ ListView listView = getListView();
+ registerForContextMenu(listView);
+ }
+
+ private void editItem(int i)
+ {
+ Intent intent = new Intent(ManageIdentities.this, EditIdentity.class);
+
+ intent.putExtra(EditIdentity.EXTRA_ACCOUNT, mAccount);
+ intent.putExtra(EditIdentity.EXTRA_IDENTITY, mAccount.getIdentity(i));
+ intent.putExtra(EditIdentity.EXTRA_IDENTITY_INDEX, i);
+ startActivityForResult(intent, ACTIVITY_EDIT_IDENTITY);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu)
+ {
+ super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.manage_identities_option, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item)
+ {
+ switch (item.getItemId())
+ {
+ case R.id.new_identity:
+ Intent intent = new Intent(ManageIdentities.this, EditIdentity.class);
+
+ intent.putExtra(EditIdentity.EXTRA_ACCOUNT, mAccount);
+ startActivityForResult(intent, ACTIVITY_EDIT_IDENTITY);
+ break;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ return true;
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
+ {
+ super.onCreateContextMenu(menu, v, menuInfo);
+ menu.setHeaderTitle(R.string.manage_identities_context_menu_title);
+ getMenuInflater().inflate(R.menu.manage_identities_context, menu);
+ }
+
+ public boolean onContextItemSelected(MenuItem item)
+ {
+ AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo)item.getMenuInfo();
+ switch (item.getItemId())
+ {
+ case R.id.edit:
+ editItem(menuInfo.position);
+ break;
+ case R.id.up:
+ if (menuInfo.position > 0)
+ {
+ Account.Identity identity = identities.remove(menuInfo.position);
+ identities.add(menuInfo.position - 1, identity);
+ mIdentitiesChanged = true;
+ refreshView();
+ }
+
+ break;
+ case R.id.down:
+ if (menuInfo.position < identities.size() - 1)
+ {
+ Account.Identity identity = identities.remove(menuInfo.position);
+ identities.add(menuInfo.position + 1, identity);
+ mIdentitiesChanged = true;
+ refreshView();
+ }
+ break;
+ case R.id.top:
+ Account.Identity identity = identities.remove(menuInfo.position);
+ identities.add(0, identity);
+ mIdentitiesChanged = true;
+ refreshView();
+ break;
+ case R.id.remove:
+ if (identities.size() > 1)
+ {
+ identities.remove(menuInfo.position);
+ mIdentitiesChanged = true;
+ refreshView();
+ }
+ else
+ {
+ Toast.makeText(this, getString(R.string.no_removable_identity),
+ Toast.LENGTH_LONG).show();
+ }
+ break;
+ }
+ return true;
+ }
+
+
+ @Override
+ public void onResume()
+ {
+ super.onResume();
+ mAccount.refresh(Preferences.getPreferences(getApplication().getApplicationContext()));
+ refreshView();
+ }
+
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event)
+ {
+ if (keyCode == KeyEvent.KEYCODE_BACK)
+ {
+ saveIdentities();
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ private void saveIdentities()
+ {
+ if (mIdentitiesChanged)
+ {
+ mAccount.setIdentities(identities);
+ mAccount.save(Preferences.getPreferences(getApplication().getApplicationContext()));
+ }
+ finish();
+ }
+}
diff --git a/src/com/android/email/activity/MessageCompose.java b/src/com/android/email/activity/MessageCompose.java
index 6543ee10d..f355f8653 100644
--- a/src/com/android/email/activity/MessageCompose.java
+++ b/src/com/android/email/activity/MessageCompose.java
@@ -4,6 +4,7 @@ package com.android.email.activity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
+import java.util.StringTokenizer;
import com.android.email.K9Activity;
import android.content.ContentResolver;
@@ -68,6 +69,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
private static final String ACTION_FORWARD = "com.android.email.intent.action.FORWARD";
private static final String ACTION_EDIT_DRAFT = "com.android.email.intent.action.EDIT_DRAFT";
+
private static final String EXTRA_ACCOUNT = "account";
private static final String EXTRA_FOLDER = "folder";
private static final String EXTRA_MESSAGE = "message";
@@ -84,6 +86,10 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
"com.android.email.activity.MessageCompose.stateKeySourceMessageProced";
private static final String STATE_KEY_DRAFT_UID =
"com.android.email.activity.MessageCompose.draftUid";
+ private static final String STATE_IDENTITY_CHANGED =
+ "com.android.email.activity.MessageCompose.identityChanged";
+ private static final String STATE_IDENTITY =
+ "com.android.email.activity.MessageCompose.identity";
private static final int MSG_PROGRESS_ON = 1;
private static final int MSG_PROGRESS_OFF = 2;
@@ -93,8 +99,12 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
private static final int MSG_DISCARDED_DRAFT = 6;
private static final int ACTIVITY_REQUEST_PICK_ATTACHMENT = 1;
+ private static final int ACTIVITY_CHOOSE_IDENTITY = 2;
private Account mAccount;
+ private Account.Identity mIdentity;
+ private boolean mIdentityChanged = false;
+ private boolean mSignatureChanged = false;
private String mFolder;
private String mSourceMessageUid;
private Message mSourceMessage;
@@ -105,18 +115,18 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
*/
private boolean mSourceMessageProcessed = false;
+
+ private TextView mFromView;
private MultiAutoCompleteTextView mToView;
private MultiAutoCompleteTextView mCcView;
private MultiAutoCompleteTextView mBccView;
private EditText mSubjectView;
+ private EditText mSignatureView;
private EditText mMessageContentView;
- private Button mSendButton;
- private Button mDiscardButton;
- private Button mSaveButton;
private LinearLayout mAttachments;
private View mQuotedTextBar;
private ImageButton mQuotedTextDelete;
- private WebView mQuotedText;
+ private EditText mQuotedText;
private boolean mDraftNeedsSaving = false;
@@ -258,15 +268,22 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
mAddressAdapter = new EmailAddressAdapter(this);
mAddressValidator = new EmailAddressValidator();
+
+ mFromView = (TextView)findViewById(R.id.from);
mToView = (MultiAutoCompleteTextView)findViewById(R.id.to);
mCcView = (MultiAutoCompleteTextView)findViewById(R.id.cc);
mBccView = (MultiAutoCompleteTextView)findViewById(R.id.bcc);
mSubjectView = (EditText)findViewById(R.id.subject);
+
+ EditText upperSignature = (EditText)findViewById(R.id.upper_signature);
+ EditText lowerSignature = (EditText)findViewById(R.id.lower_signature);
+
+
mMessageContentView = (EditText)findViewById(R.id.message_content);
mAttachments = (LinearLayout)findViewById(R.id.attachments);
mQuotedTextBar = findViewById(R.id.quoted_text_bar);
mQuotedTextDelete = (ImageButton)findViewById(R.id.quoted_text_delete);
- mQuotedText = (WebView)findViewById(R.id.quoted_text);
+ mQuotedText = (EditText)findViewById(R.id.quoted_text);
TextWatcher watcher = new TextWatcher() {
public void beforeTextChanged(CharSequence s, int start,
@@ -280,10 +297,24 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
public void afterTextChanged(android.text.Editable s) { }
};
+ TextWatcher sigwatcher = new TextWatcher() {
+ public void beforeTextChanged(CharSequence s, int start,
+ int before, int after) { }
+
+ public void onTextChanged(CharSequence s, int start,
+ int before, int count) {
+ mDraftNeedsSaving = true;
+ mSignatureChanged = true;
+ }
+
+ public void afterTextChanged(android.text.Editable s) { }
+ };
+
mToView.addTextChangedListener(watcher);
mCcView.addTextChangedListener(watcher);
mBccView.addTextChangedListener(watcher);
mSubjectView.addTextChangedListener(watcher);
+
mMessageContentView.addTextChangedListener(watcher);
/*
@@ -295,6 +326,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
mQuotedTextDelete.setOnClickListener(this);
+ mFromView.setVisibility(View.GONE);
+
mToView.setAdapter(mAddressAdapter);
mToView.setTokenizer(new Rfc822Tokenizer());
mToView.setValidator(mAddressValidator);
@@ -447,6 +480,26 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
mSourceMessageUid = (String) intent.getStringExtra(EXTRA_MESSAGE);
}
+ if (mIdentity == null)
+ {
+ mIdentity = mAccount.getIdentity(0);
+ }
+
+ if (mAccount.isSignatureBeforeQuotedText())
+ {
+ mSignatureView = upperSignature;
+ lowerSignature.setVisibility(View.GONE);
+ }
+ else
+ {
+ mSignatureView = lowerSignature;
+ upperSignature.setVisibility(View.GONE);
+ }
+ mSignatureView.addTextChangedListener(sigwatcher);
+
+ updateFrom();
+ updateSignature();
+
Log.d(Email.LOG_TAG, "action = " + action + ", mAccount = " + mAccount + ", mFolder = " + mFolder + ", mSourceMessageUid = " + mSourceMessageUid);
if ((ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action)) && mAccount != null && mFolder != null && mSourceMessageUid != null) {
Log.d(Email.LOG_TAG, "Setting message ANSWERED flag to true");
@@ -471,12 +524,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
}
if (!ACTION_EDIT_DRAFT.equals(action)) {
- if (mAccount.isSignatureBeforeQuotedText()) {
- String signature = getSignature();
- if (signature!=null) {
- mMessageContentView.setText(signature);
- }
- }
addAddress(mBccView, new Address(mAccount.getAlwaysBcc(), ""));
}
@@ -518,6 +565,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
outState.putBoolean(STATE_KEY_QUOTED_TEXT_SHOWN, mQuotedTextBar.getVisibility() == View.VISIBLE);
outState.putBoolean(STATE_KEY_SOURCE_MESSAGE_PROCED, mSourceMessageProcessed);
outState.putString(STATE_KEY_DRAFT_UID, mDraftUid);
+ outState.putSerializable(STATE_IDENTITY, mIdentity);
+ outState.putBoolean(STATE_IDENTITY_CHANGED, mIdentityChanged);
}
@Override
@@ -535,6 +584,11 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
mQuotedTextBar.setVisibility(savedInstanceState.getBoolean(STATE_KEY_QUOTED_TEXT_SHOWN) ? View.VISIBLE : View.GONE);
mQuotedText.setVisibility(savedInstanceState.getBoolean(STATE_KEY_QUOTED_TEXT_SHOWN) ? View.VISIBLE : View.GONE);
mDraftUid = savedInstanceState.getString(STATE_KEY_DRAFT_UID);
+ mIdentity = (Account.Identity)savedInstanceState.getSerializable(STATE_IDENTITY);
+ mIdentityChanged = savedInstanceState.getBoolean(STATE_IDENTITY_CHANGED);
+ updateFrom();
+ updateSignature();
+
mDraftNeedsSaving = false;
}
@@ -570,10 +624,10 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
return addresses;
}
- private MimeMessage createMessage() throws MessagingException {
+ private MimeMessage createMessage(boolean appendSig) throws MessagingException {
MimeMessage message = new MimeMessage();
message.setSentDate(new Date());
- Address from = new Address(mAccount.getEmail(), mAccount.getName());
+ Address from = new Address(mIdentity.getEmail(), mIdentity.getName());
message.setFrom(from);
message.setRecipients(RecipientType.TO, getAddresses(mToView));
message.setRecipients(RecipientType.CC, getAddresses(mCcView));
@@ -582,49 +636,25 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
// XXX TODO - not sure why this won't add header
// message.setHeader("X-User-Agent", getString(R.string.message_header_mua));
-
-
/*
* Build the Body that will contain the text of the message. We'll decide where to
* include it later.
*/
String text = mMessageContentView.getText().toString();
-
- String action = getIntent().getAction();
- if (mQuotedTextBar.getVisibility() == View.VISIBLE) {
- String quotedText = null;
- Part part = MimeUtility.findFirstPartByMimeType(mSourceMessage, "text/plain");
- if (part != null) {
- quotedText = MimeUtility.getTextFromPart(part);
- }
- if (ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action)) {
- text += String.format( getString(R.string.message_compose_reply_header_fmt), Address.toString(mSourceMessage.getFrom()));
- if (quotedText != null) {
- text += quotedText.replaceAll("(?m)^", ">");
- }
- }
- else if (ACTION_FORWARD.equals(action)) {
- text += String.format(
- getString(R.string.message_compose_fwd_header_fmt),
- mSourceMessage.getSubject(),
- Address.toString(mSourceMessage.getFrom()),
- Address.toString( mSourceMessage.getRecipients(RecipientType.TO)),
- Address.toString( mSourceMessage.getRecipients(RecipientType.CC)));
- if (quotedText != null) {
- text += quotedText;
- }
- }
+ if (appendSig && mAccount.isSignatureBeforeQuotedText()) {
+ text = appendSignature(text);
}
- if (!mAccount.isSignatureBeforeQuotedText()
- && !ACTION_EDIT_DRAFT.equals(action)) {
- String signature = getSignature();
- if (signature!=null) {
- text += signature;
- }
- }//if isSignatureBeforeQuotedText DRAFT
+ if (mQuotedTextBar.getVisibility() == View.VISIBLE) {
+ text += "\n" + mQuotedText.getText().toString();
+ }
+
+ if (appendSig && mAccount.isSignatureBeforeQuotedText() == false) {
+ text = appendSignature(text);
+ }
+
TextBody body = new TextBody(text);
if (mAttachments.getChildCount() > 0) {
@@ -660,18 +690,15 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
return message;
}
- private String getSignature() {
- String mSignature;
- mSignature = mAccount.getSignature();
-
- if (mSignature != null && !mSignature.contentEquals("")) {
- return "\n--\n" + mAccount.getSignature();
- }
- else {
- return null;
+ private String appendSignature (String text) {
+ String signature= mSignatureView.getText().toString();
+
+ if (signature != null && ! signature.contentEquals("")){
+ text += "\n" + signature;
}
- }
+ return text;
+ }
private void sendOrSaveMessage(boolean save) {
/*
@@ -679,7 +706,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
*/
MimeMessage message;
try {
- message = createMessage();
+ message = createMessage(!save); // Only append sig on save
}
catch (MessagingException me) {
Log.e(Email.LOG_TAG, "Failed to create new message for send or save.", me);
@@ -700,6 +727,26 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
*/
message.setUid(mSourceMessageUid);
}
+
+ String k9identity = Utility.base64Encode("" + mMessageContentView.getText().toString().length());
+
+ if (mIdentityChanged || mSignatureChanged)
+ {
+ String signature = mSignatureView.getText().toString();
+ k9identity += ":" + Utility.base64Encode(signature) ;
+ if (mIdentityChanged)
+ {
+
+ String name = mIdentity.getName();
+ String email = mIdentity.getEmail();
+
+ k9identity += ":" + Utility.base64Encode(name) + ":" + Utility.base64Encode(email);
+ }
+ }
+
+ Log.d(Email.LOG_TAG, "Saving identity: " + k9identity);
+ message.setHeader(Email.K9MAIL_IDENTITY, k9identity);
+
MessagingController.getInstance(getApplication()).saveDraft(mAccount, message);
mDraftUid = message.getUid();
@@ -827,11 +874,50 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if(resultCode != RESULT_OK)
+ return;
if (data == null) {
return;
}
+ switch(requestCode) {
+ case ACTIVITY_REQUEST_PICK_ATTACHMENT:
+
addAttachment(data.getData());
mDraftNeedsSaving = true;
+ break;
+ case ACTIVITY_CHOOSE_IDENTITY:
+ onIdentityChosen(data);
+ break;
+ }
+ }
+
+ private void onIdentityChosen(Intent intent)
+ {
+ Bundle bundle = intent.getExtras();;
+ mIdentity = (Account.Identity)bundle.getSerializable(ChooseIdentity.EXTRA_IDENTITY);
+// if (mIdentityChanged == false)
+// {
+// Toast.makeText(this, getString(R.string.identity_will_not_be_saved),
+// Toast.LENGTH_LONG).show();
+// }
+ mIdentityChanged = true;
+ mDraftNeedsSaving = true;
+ updateFrom();
+ updateSignature();
+ }
+
+ private void updateFrom()
+ {
+ if (mIdentityChanged)
+ {
+ mFromView.setVisibility(View.VISIBLE);
+ }
+ mFromView.setText(getString(R.string.message_view_from_format, mIdentity.getName(), mIdentity.getEmail()));
+ }
+
+ private void updateSignature()
+ {
+ mSignatureView.setText(mIdentity.getSignature());
}
public void onClick(View view) {
@@ -870,15 +956,34 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
case R.id.add_attachment:
onAddAttachment();
break;
+ case R.id.choose_identity:
+ onChooseIdentity();
+ break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
+ private void onChooseIdentity()
+ {
+ if (mAccount.getIdentities().size() > 1)
+ {
+ Intent intent = new Intent(this, ChooseIdentity.class);
+ intent.putExtra(ChooseIdentity.EXTRA_ACCOUNT, mAccount);
+ startActivityForResult(intent, ACTIVITY_CHOOSE_IDENTITY);
+ }
+ else
+ {
+ Toast.makeText(this, getString(R.string.no_identities),
+ Toast.LENGTH_LONG).show();
+ }
+ }
+
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.message_compose_option, menu);
+
return true;
}
@@ -942,9 +1047,24 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
else {
addAddresses(mToView, replyToAddresses = message.getFrom());
}
+
+ Part part = MimeUtility.findFirstPartByMimeType(mSourceMessage,
+ "text/plain");
+ if (part != null) {
+ String quotedText = String.format(
+ getString(R.string.message_compose_reply_header_fmt),
+ Address.toString(mSourceMessage.getFrom()));
+
+ quotedText += MimeUtility.getTextFromPart(part).replaceAll("(?m)^", ">");
+ mQuotedText.setText(quotedText);
+
+ mQuotedTextBar.setVisibility(View.VISIBLE);
+ mQuotedText.setVisibility(View.VISIBLE);
+ }
+
if (ACTION_REPLY_ALL.equals(action)) {
for (Address address : message.getRecipients(RecipientType.TO)) {
- if (!address.getAddress().equalsIgnoreCase(mAccount.getEmail())) {
+ if (!mAccount.isAnIdentity(address)) {
addAddress(mToView, address);
}
}
@@ -957,20 +1077,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
mCcView.setVisibility(View.VISIBLE);
}
}
-
- Part part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
- if (part == null) {
- part = MimeUtility.findFirstPartByMimeType(message, "text/html");
- }
- if (part != null) {
- String text = MimeUtility.getTextFromPart(part);
- if (text != null) {
- mQuotedTextBar.setVisibility(View.VISIBLE);
- mQuotedText.setVisibility(View.VISIBLE);
- mQuotedText.loadDataWithBaseURL("email://", text, part.getMimeType(), "utf-8", null);
- }
- }
- }
+ }
catch (MessagingException me) {
/*
* This really should not happen at this point but if it does it's okay.
@@ -986,17 +1093,26 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
else {
mSubjectView.setText(message.getSubject());
}
-
Part part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
if (part == null) {
part = MimeUtility.findFirstPartByMimeType(message, "text/html");
}
if (part != null) {
- String text = MimeUtility.getTextFromPart(part);
- if (text != null) {
+ String quotedText = MimeUtility.getTextFromPart(part);
+ if (quotedText != null) {
+ String text = String.format(
+ getString(R.string.message_compose_fwd_header_fmt),
+ mSourceMessage.getSubject(),
+ Address.toString(mSourceMessage.getFrom()),
+ Address.toString(
+ mSourceMessage.getRecipients(RecipientType.TO)),
+ Address.toString(
+ mSourceMessage.getRecipients(RecipientType.CC)));
+
+ text += quotedText;
+ mQuotedText.setText(text);
mQuotedTextBar.setVisibility(View.VISIBLE);
mQuotedText.setVisibility(View.VISIBLE);
- mQuotedText.loadDataWithBaseURL("email://", text, part.getMimeType(), "utf-8", null);
}
}
if (!mSourceMessageProcessed) {
@@ -1024,13 +1140,106 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
addAddresses(mBccView, message.getRecipients(RecipientType.BCC));
mBccView.setVisibility(View.VISIBLE);
}
+
+ if (!mSourceMessageProcessed) {
+ loadAttachments(message, 0);
+ }
+ Integer bodyLength = null;
+ String[] k9identities = message.getHeader(Email.K9MAIL_IDENTITY);
+ if (k9identities != null && k9identities.length > 0)
+ {
+ String k9identity = k9identities[0];
+
+ if (k9identity != null)
+ {
+ Log.d(Email.LOG_TAG, "Got a saved identity: " + k9identity);
+ StringTokenizer tokens = new StringTokenizer(k9identity, ":", false);
+
+ String bodyLengthS = null;
+ String name = null;
+ String email = null;
+ String signature = null;
+ if (tokens.hasMoreTokens())
+ {
+ bodyLengthS = Utility.base64Decode(tokens.nextToken());
+ try
+ {
+ bodyLength = Integer.parseInt(bodyLengthS);
+ }
+ catch (Exception e)
+ {
+ Log.e(Email.LOG_TAG, "Unable to parse bodyLength '" + bodyLengthS + "'");
+ }
+ }
+ if (tokens.hasMoreTokens())
+ {
+ signature = Utility.base64Decode(tokens.nextToken());
+ }
+ if (tokens.hasMoreTokens())
+ {
+ name = Utility.base64Decode(tokens.nextToken());
+ }
+ if (tokens.hasMoreTokens())
+ {
+ email = Utility.base64Decode(tokens.nextToken());
+ }
+
+ Account.Identity newIdentity= mAccount.new Identity();
+ if (signature != null)
+ {
+ newIdentity.setSignature(signature);
+ mSignatureChanged = true;
+ }
+ else
+ {
+ newIdentity.setSignature(mIdentity.getSignature());
+ }
+
+ if (name != null)
+ {
+ newIdentity.setName(name);
+ mIdentityChanged = true;
+ }
+ else
+ {
+ newIdentity.setName(mIdentity.getName());
+ }
+
+ if (email != null)
+ {
+ newIdentity.setEmail(email);
+ mIdentityChanged = true;
+ }
+ else
+ {
+ newIdentity.setEmail(mIdentity.getEmail());
+ }
+
+ mIdentity = newIdentity;
+
+ updateSignature();
+ updateFrom();
+
+ }
+ }
Part part = MimeUtility.findFirstPartByMimeType(message, "text/plain");
if (part != null) {
String text = MimeUtility.getTextFromPart(part);
+ if (bodyLength != null && bodyLength + 1 < text.length()) // + 1 to get rid of the newline we added when saving the draft
+ {
+ String bodyText = text.substring(0, bodyLength);
+ String quotedText = text.substring(bodyLength + 1, text.length());
+
+ mMessageContentView.setText(bodyText);
+ mQuotedText.setText(quotedText);
+
+ mQuotedTextBar.setVisibility(View.VISIBLE);
+ mQuotedText.setVisibility(View.VISIBLE);
+ }
+ else
+ {
mMessageContentView.setText(text);
}
- if (!mSourceMessageProcessed) {
- loadAttachments(message, 0);
}
}
catch (MessagingException me) {
diff --git a/src/com/android/email/activity/setup/AccountSettings.java b/src/com/android/email/activity/setup/AccountSettings.java
index e0c1aba3f..dd2f0be4a 100644
--- a/src/com/android/email/activity/setup/AccountSettings.java
+++ b/src/com/android/email/activity/setup/AccountSettings.java
@@ -23,15 +23,20 @@ import com.android.email.Email;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.activity.ChooseFolder;
+import com.android.email.activity.ChooseIdentity;
+import com.android.email.activity.ManageIdentities;
public class AccountSettings extends K9PreferenceActivity {
private static final String EXTRA_ACCOUNT = "account";
private static final int SELECT_AUTO_EXPAND_FOLDER = 1;
+ private static final int ACTIVITY_MANAGE_IDENTITIES = 2;
+
private static final String PREFERENCE_TOP_CATERGORY = "account_settings";
private static final String PREFERENCE_DESCRIPTION = "account_description";
private static final String PREFERENCE_COMPOSITION = "composition";
+ private static final String PREFERENCE_MANAGE_IDENTITIES = "manage_identities";
private static final String PREFERENCE_FREQUENCY = "account_check_frequency";
private static final String PREFERENCE_DISPLAY_COUNT = "account_display_count";
private static final String PREFERENCE_DEFAULT = "account_default";
@@ -226,6 +231,14 @@ public class AccountSettings extends K9PreferenceActivity {
}
});
+ findPreference(PREFERENCE_MANAGE_IDENTITIES).setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ public boolean onPreferenceClick(Preference preference) {
+ onManageIdentities();
+ return true;
+ }
+ });
+
findPreference(PREFERENCE_INCOMING).setOnPreferenceClickListener(
new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
@@ -296,6 +309,12 @@ public class AccountSettings extends K9PreferenceActivity {
AccountSetupComposition.actionEditCompositionSettings(this, mAccount);
}
+ private void onManageIdentities() {
+ Intent intent = new Intent(this, ManageIdentities.class);
+ intent.putExtra(ChooseIdentity.EXTRA_ACCOUNT, mAccount);
+ startActivityForResult(intent, ACTIVITY_MANAGE_IDENTITIES);
+ }
+
private void onIncomingSettings() {
AccountSetupIncoming.actionEditIncomingSettings(this, mAccount);
}
diff --git a/src/com/android/email/mail/internet/MimeHeader.java b/src/com/android/email/mail/internet/MimeHeader.java
index 7a233d054..24aad4d07 100644
--- a/src/com/android/email/mail/internet/MimeHeader.java
+++ b/src/com/android/email/mail/internet/MimeHeader.java
@@ -6,7 +6,9 @@ import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
+import java.util.List;
+import com.android.email.Email;
import com.android.email.Utility;
import com.android.email.mail.MessagingException;
@@ -39,7 +41,7 @@ public class MimeHeader {
mFields.clear();
}
- public String getFirstHeader(String name) throws MessagingException {
+ public String getFirstHeader(String name) {
String[] header = getHeader(name);
if (header == null) {
return null;
@@ -47,11 +49,11 @@ public class MimeHeader {
return header[0];
}
- public void addHeader(String name, String value) throws MessagingException {
+ public void addHeader(String name, String value) {
mFields.add(new Field(name, MimeUtility.foldAndEncode(value)));
}
- public void setHeader(String name, String value) throws MessagingException {
+ public void setHeader(String name, String value) {
if (name == null || value == null) {
return;
}
@@ -59,7 +61,16 @@ public class MimeHeader {
addHeader(name, value);
}
- public String[] getHeader(String name) throws MessagingException {
+ public List getHeaderNames()
+ {
+ ArrayList names = new ArrayList();
+ for (Field field : mFields) {
+ names.add(field.name);
+ }
+ return names;
+ }
+
+ public String[] getHeader(String name) {
ArrayList values = new ArrayList();
for (Field field : mFields) {
if (field.name.equalsIgnoreCase(name)) {
@@ -72,7 +83,7 @@ public class MimeHeader {
return values.toArray(new String[] {});
}
- public void removeHeader(String name) throws MessagingException {
+ public void removeHeader(String name) {
ArrayList removeFields = new ArrayList();
for (Field field : mFields) {
if (field.name.equalsIgnoreCase(name)) {
diff --git a/src/com/android/email/mail/internet/MimeMessage.java b/src/com/android/email/mail/internet/MimeMessage.java
index fa52822fd..4eaf362dd 100644
--- a/src/com/android/email/mail/internet/MimeMessage.java
+++ b/src/com/android/email/mail/internet/MimeMessage.java
@@ -8,6 +8,7 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.List;
import java.util.Locale;
import java.util.Stack;
@@ -43,21 +44,9 @@ public class MimeMessage extends Message {
protected int mSize;
public MimeMessage() {
- setGeneratedMessageId();
- }
-
-
- public void setGeneratedMessageId () {
- /*
- * Every new messages gets a Message-ID
- */
- try {
setHeader("Message-ID", generateMessageId());
+
}
- catch (MessagingException me) {
- throw new RuntimeException("Unable to create MimeMessage", me);
- }
- }
private String generateMessageId() {
StringBuffer sb = new StringBuffer();
@@ -280,26 +269,31 @@ public class MimeMessage extends Message {
}
}
- protected String getFirstHeader(String name) throws MessagingException {
+ protected String getFirstHeader(String name) {
return mHeader.getFirstHeader(name);
}
- public void addHeader(String name, String value) throws MessagingException {
+ public void addHeader(String name, String value) {
mHeader.addHeader(name, value);
}
- public void setHeader(String name, String value) throws MessagingException {
+ public void setHeader(String name, String value) {
mHeader.setHeader(name, value);
}
- public String[] getHeader(String name) throws MessagingException {
+ public String[] getHeader(String name) {
return mHeader.getHeader(name);
}
- public void removeHeader(String name) throws MessagingException {
+ public void removeHeader(String name) {
mHeader.removeHeader(name);
}
+ public List getHeaderNames()
+ {
+ return mHeader.getHeaderNames();
+ }
+
public void writeTo(OutputStream out) throws IOException, MessagingException {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
mHeader.writeTo(out);
diff --git a/src/com/android/email/mail/store/ImapStore.java b/src/com/android/email/mail/store/ImapStore.java
index c4087f906..d9cce53d4 100644
--- a/src/com/android/email/mail/store/ImapStore.java
+++ b/src/com/android/email/mail/store/ImapStore.java
@@ -723,7 +723,8 @@ public class ImapStore extends Store {
if (fp.contains(FetchProfile.Item.ENVELOPE)) {
fetchFields.add("INTERNALDATE");
fetchFields.add("RFC822.SIZE");
- fetchFields.add("BODY.PEEK[HEADER.FIELDS (date subject from content-type to cc)]");
+ fetchFields.add("BODY.PEEK[HEADER.FIELDS (date subject from content-type to cc reply-to "
+ + Email.K9MAIL_IDENTITY + ")]");
}
if (fp.contains(FetchProfile.Item.STRUCTURE)) {
fetchFields.add("BODYSTRUCTURE");
diff --git a/src/com/android/email/mail/store/LocalStore.java b/src/com/android/email/mail/store/LocalStore.java
index 2a4487f51..c1855f864 100644
--- a/src/com/android/email/mail/store/LocalStore.java
+++ b/src/com/android/email/mail/store/LocalStore.java
@@ -14,6 +14,11 @@ import java.net.URI;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import android.content.SharedPreferences;
@@ -62,10 +67,7 @@ import java.io.StringReader;
*
*/
public class LocalStore extends Store implements Serializable {
- // If you are going to change the DB_VERSION, please also go into Email.java and local for the comment
- // on LOCAL_UID_PREFIX and follow the instructions there. If you follow the instructions there,
- // please delete this comment.
- private static final int DB_VERSION = 25;
+ private static final int DB_VERSION = 26;
private static final Flag[] PERMANENT_FLAGS = { Flag.DELETED, Flag.X_DESTROYED, Flag.SEEN };
private String mPath;
@@ -74,6 +76,12 @@ public class LocalStore extends Store implements Serializable {
private Application mApplication;
private String uUid = null;
+ private static Set HEADERS_TO_SAVE = new HashSet();
+ static
+ {
+ HEADERS_TO_SAVE.add(Email.K9MAIL_IDENTITY);
+ }
+
/**
* @param uri local://localhost/path/to/database/uuid.db
*/
@@ -133,6 +141,10 @@ public class LocalStore extends Store implements Serializable {
+ "date INTEGER, flags TEXT, sender_list TEXT, to_list TEXT, cc_list TEXT, bcc_list TEXT, reply_to_list TEXT, "
+ "html_content TEXT, text_content TEXT, attachment_count INTEGER, internal_date INTEGER, message_id TEXT)");
+ mDb.execSQL("DROP TABLE IF EXISTS headers");
+ mDb.execSQL("CREATE TABLE headers (id INTEGER PRIMARY KEY, message_id INTEGER, name TEXT, value TEXT)");
+ mDb.execSQL("CREATE INDEX IF NOT EXISTS header_folder ON headers (message_id)");
+
mDb.execSQL("CREATE INDEX IF NOT EXISTS msg_uid ON messages (uid, folder_id)");
mDb.execSQL("DROP INDEX IF EXISTS msg_folder_id");
mDb.execSQL("CREATE INDEX IF NOT EXISTS msg_folder_id_date ON messages (folder_id,internal_date)");
@@ -149,7 +161,9 @@ public class LocalStore extends Store implements Serializable {
mDb.execSQL("CREATE TRIGGER delete_folder BEFORE DELETE ON folders BEGIN DELETE FROM messages WHERE old.id = folder_id; END;");
mDb.execSQL("DROP TRIGGER IF EXISTS delete_message");
- mDb.execSQL("CREATE TRIGGER delete_message BEFORE DELETE ON messages BEGIN DELETE FROM attachments WHERE old.id = message_id; END;");
+ mDb.execSQL("CREATE TRIGGER delete_message BEFORE DELETE ON messages BEGIN DELETE FROM attachments WHERE old.id = message_id; "
+ + "DELETE FROM headers where old.id = message_id; END;");
+
mDb.setVersion(DB_VERSION);
if (mDb.getVersion() != DB_VERSION) {
throw new Error("Database upgrade failed!");
@@ -913,6 +927,54 @@ public class LocalStore extends Store implements Serializable {
"LocalStore.getMessages(int, int, MessageRetrievalListener) not yet implemented");
}
+ private void populateHeaders(List messages)
+ {
+ Cursor cursor = null;
+ if (messages.size() == 0)
+ {
+ return;
+ }
+ try {
+ Map popMessages = new HashMap();
+ List ids = new ArrayList();
+ StringBuffer questions = new StringBuffer();
+
+ for (int i = 0; i < messages.size(); i++)
+ {
+ if (i != 0)
+ {
+ questions.append(", ");
+ }
+ questions.append("?");
+ LocalMessage message = messages.get(i);
+ Long id = message.getId();
+ ids.add(Long.toString(id));
+ popMessages.put(id, message);
+
+ }
+
+ cursor = mDb.rawQuery(
+ "SELECT message_id, name, value "
+ + "FROM headers " + "WHERE message_id in ( " + questions + ") ",
+ ids.toArray(new String[] {}));
+
+
+ while (cursor.moveToNext()) {
+ Long id = cursor.getLong(0);
+ String name = cursor.getString(1);
+ String value = cursor.getString(2);
+ //Log.i(Email.LOG_TAG, "Retrieved header name= " + name + ", value = " + value + " for message " + id);
+ popMessages.get(id).addHeader(name, value);
+ }
+ }
+ finally
+ {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ }
+
@Override
public Message getMessage(String uid) throws MessagingException {
open(OpenMode.READ_WRITE);
@@ -930,6 +992,9 @@ public class LocalStore extends Store implements Serializable {
return null;
}
populateMessageFromGetMessageCursor(message, cursor);
+ ArrayList messages = new ArrayList();
+ messages.add(message);
+ populateHeaders(messages);
}
finally {
if (cursor != null) {
@@ -942,7 +1007,7 @@ public class LocalStore extends Store implements Serializable {
@Override
public Message[] getMessages(MessageRetrievalListener listener) throws MessagingException {
open(OpenMode.READ_WRITE);
- ArrayList messages = new ArrayList();
+ ArrayList messages = new ArrayList();
Cursor cursor = null;
try {
// pull out messages most recent first, since that's what the default sort is
@@ -959,12 +1024,14 @@ public class LocalStore extends Store implements Serializable {
while (cursor.moveToNext()) {
LocalMessage message = new LocalMessage(null, this);
populateMessageFromGetMessageCursor(message, cursor);
+
messages.add(message);
if (listener != null) {
listener.messageFinished(message, i, -1);
}
i++;
}
+ populateHeaders(messages);
}
finally {
if (cursor != null) {
@@ -1126,6 +1193,7 @@ public class LocalStore extends Store implements Serializable {
for (Part attachment : attachments) {
saveAttachment(messageId, attachment, copy);
}
+ saveHeaders(messageId, (MimeMessage)message);
} catch (Exception e) {
throw new MessagingException("Error appending message", e);
}
@@ -1204,11 +1272,41 @@ public class LocalStore extends Store implements Serializable {
Part attachment = attachments.get(i);
saveAttachment(message.mId, attachment, false);
}
+ saveHeaders(message.getId(), message);
} catch (Exception e) {
throw new MessagingException("Error appending message", e);
}
}
+ private void saveHeaders(long id, MimeMessage message)
+ {
+ deleteHeaders(id);
+ for (String name : message.getHeaderNames())
+ {
+ if (HEADERS_TO_SAVE.contains(name))
+ {
+ String[] values = message.getHeader(name);
+ for (String value : values)
+ {
+ ContentValues cv = new ContentValues();
+ cv.put("message_id", id);
+ cv.put("name", name);
+ cv.put("value", value);
+ //Log.i(Email.LOG_TAG, "Saving header name = " + name + ", value = " + value);
+ mDb.insert("headers", "name", cv);
+ }
+ }
+ }
+ }
+
+ private void deleteHeaders(long id)
+ {
+ mDb.execSQL("DELETE FROM headers WHERE id = ?",
+ new Object[] {
+ id
+ });
+ }
+
/**
* @param messageId
* @param attachment
@@ -1535,10 +1633,6 @@ public class LocalStore extends Store implements Serializable {
public LocalMessage() {
}
-
- // We don't want to do this for local messages
- @Override public void setGeneratedMessageId () {}
-
LocalMessage(String uid, Folder folder) throws MessagingException {
this.mUid = uid;
@@ -1620,16 +1714,19 @@ public class LocalStore extends Store implements Serializable {
/*
* Delete all of the messages' attachments to save space.
*/
- // shouldn't the trigger take care of this? -- danapple
mDb.execSQL("DELETE FROM attachments WHERE id = ?",
new Object[] {
mId
});
+
+ ((LocalFolder)mFolder).deleteHeaders(mId);
+
}
else if (flag == Flag.X_DESTROYED && set) {
((LocalFolder) mFolder).deleteAttachments(getUid());
mDb.execSQL("DELETE FROM messages WHERE id = ?",
new Object[] { mId });
+ ((LocalFolder)mFolder).deleteHeaders(mId);
}
/*