1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-12-24 08:38:51 -05:00
This commit is contained in:
Jesse Vincent 2011-04-12 22:16:22 +10:00
parent c891a5f00b
commit 0174988d27
20 changed files with 243 additions and 246 deletions

View File

@ -942,11 +942,11 @@ public class K9 extends Application {
}
public static boolean confirmSpam() {
return mConfirmSpam;
return mConfirmSpam;
}
public static void setConfirmSpam(final boolean confirm) {
mConfirmSpam = confirm;
mConfirmSpam = confirm;
}
public static boolean confirmMarkAllAsRead() {

View File

@ -457,66 +457,66 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
switch (id) {
case DIALOG_REMOVE_ACCOUNT:
return ConfirmationDialog.create(this, id,
R.string.account_delete_dlg_title,
getString(R.string.account_delete_dlg_instructions_fmt,
mSelectedContextAccount.getDescription()),
R.string.okay_action,
R.string.cancel_action,
new Runnable() {
@Override
public void run() {
if (mSelectedContextAccount instanceof Account) {
Account realAccount = (Account)mSelectedContextAccount;
try {
realAccount.getLocalStore().delete();
} catch (Exception e) {
// Ignore, this may lead to localStores on sd-cards that are
// currently not inserted to be left
}
MessagingController.getInstance(getApplication())
.notifyAccountCancel(Accounts.this, realAccount);
Preferences.getPreferences(Accounts.this).deleteAccount(realAccount);
K9.setServicesEnabled(Accounts.this);
refresh();
}
R.string.account_delete_dlg_title,
getString(R.string.account_delete_dlg_instructions_fmt,
mSelectedContextAccount.getDescription()),
R.string.okay_action,
R.string.cancel_action,
new Runnable() {
@Override
public void run() {
if (mSelectedContextAccount instanceof Account) {
Account realAccount = (Account)mSelectedContextAccount;
try {
realAccount.getLocalStore().delete();
} catch (Exception e) {
// Ignore, this may lead to localStores on sd-cards that are
// currently not inserted to be left
}
});
MessagingController.getInstance(getApplication())
.notifyAccountCancel(Accounts.this, realAccount);
Preferences.getPreferences(Accounts.this).deleteAccount(realAccount);
K9.setServicesEnabled(Accounts.this);
refresh();
}
}
});
case DIALOG_CLEAR_ACCOUNT:
return ConfirmationDialog.create(this, id,
R.string.account_clear_dlg_title,
getString(R.string.account_clear_dlg_instructions_fmt,
mSelectedContextAccount.getDescription()),
R.string.okay_action,
R.string.cancel_action,
new Runnable() {
@Override
public void run() {
if (mSelectedContextAccount instanceof Account) {
Account realAccount = (Account)mSelectedContextAccount;
mHandler.workingAccount(realAccount, R.string.clearing_account);
MessagingController.getInstance(getApplication()).clear(realAccount, null);
}
}
});
R.string.account_clear_dlg_title,
getString(R.string.account_clear_dlg_instructions_fmt,
mSelectedContextAccount.getDescription()),
R.string.okay_action,
R.string.cancel_action,
new Runnable() {
@Override
public void run() {
if (mSelectedContextAccount instanceof Account) {
Account realAccount = (Account)mSelectedContextAccount;
mHandler.workingAccount(realAccount, R.string.clearing_account);
MessagingController.getInstance(getApplication()).clear(realAccount, null);
}
}
});
case DIALOG_RECREATE_ACCOUNT:
return ConfirmationDialog.create(this, id,
R.string.account_recreate_dlg_title,
getString(R.string.account_recreate_dlg_instructions_fmt,
mSelectedContextAccount.getDescription()),
R.string.okay_action,
R.string.cancel_action,
new Runnable() {
@Override
public void run() {
if (mSelectedContextAccount instanceof Account) {
Account realAccount = (Account)mSelectedContextAccount;
mHandler.workingAccount(realAccount, R.string.recreating_account);
MessagingController.getInstance(getApplication()).recreate(realAccount, null);
}
}
});
R.string.account_recreate_dlg_title,
getString(R.string.account_recreate_dlg_instructions_fmt,
mSelectedContextAccount.getDescription()),
R.string.okay_action,
R.string.cancel_action,
new Runnable() {
@Override
public void run() {
if (mSelectedContextAccount instanceof Account) {
Account realAccount = (Account)mSelectedContextAccount;
mHandler.workingAccount(realAccount, R.string.recreating_account);
MessagingController.getInstance(getApplication()).recreate(realAccount, null);
}
}
});
}
return super.onCreateDialog(id);
}

View File

@ -20,27 +20,27 @@ public class ConfirmationDialog {
* @return A confirmation dialog with the supplied arguments
*/
public static Dialog create(final Activity activity, final int dialogId, final int title,
final String message, final int confirmButton, final int cancelButton,
final Runnable action) {
final String message, final int confirmButton, final int cancelButton,
final Runnable action) {
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(title);
builder.setMessage(message);
builder.setPositiveButton(confirmButton,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
activity.dismissDialog(dialogId);
action.run();
}
});
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
activity.dismissDialog(dialogId);
action.run();
}
});
builder.setNegativeButton(cancelButton,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
activity.dismissDialog(dialogId);
}
});
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
activity.dismissDialog(dialogId);
}
});
return builder.create();
}
@ -58,10 +58,10 @@ public class ConfirmationDialog {
* @see #create(Activity,int,int,String,int,int,Runnable)
*/
public static Dialog create(final Activity activity, final int dialogId, final int title,
final int message, final int confirmButton, final int cancelButton,
final Runnable action) {
final int message, final int confirmButton, final int cancelButton,
final Runnable action) {
return create(activity, dialogId, title, activity.getString(message), confirmButton,
cancelButton, action);
cancelButton, action);
}
}

View File

@ -641,10 +641,12 @@ public class FolderList extends K9ListActivity {
private void markAllAsRead() {
try {
MessagingController.getInstance(getApplication())
.markAllMessagesRead(mAccount, mSelectedContextFolder.name);
.markAllMessagesRead(mAccount, mSelectedContextFolder.name);
mSelectedContextFolder.unreadMessageCount = 0;
mHandler.dataChanged();
} catch (Exception e) { /* Ignore */ }
} catch (Exception e) {
/* Ignore */
}
}
@Override
@ -652,17 +654,17 @@ public class FolderList extends K9ListActivity {
switch (id) {
case DIALOG_MARK_ALL_AS_READ:
return ConfirmationDialog.create(this, id,
R.string.mark_all_as_read_dlg_title,
getString(R.string.mark_all_as_read_dlg_instructions_fmt,
mSelectedContextFolder.displayName),
R.string.okay_action,
R.string.cancel_action,
new Runnable() {
@Override
public void run() {
markAllAsRead();
}
});
R.string.mark_all_as_read_dlg_title,
getString(R.string.mark_all_as_read_dlg_instructions_fmt,
mSelectedContextFolder.displayName),
R.string.okay_action,
R.string.cancel_action,
new Runnable() {
@Override
public void run() {
markAllAsRead();
}
});
}
return super.onCreateDialog(id);

View File

@ -1121,7 +1121,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
*/
bp.addHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, String.format(
"attachment;\n filename=\"%s\";\n size=%d",
EncoderUtil.encodeIfNecessary(attachment.name,
EncoderUtil.encodeIfNecessary(attachment.name,
EncoderUtil.Usage.WORD_ENTITY, 7),
attachment.size));

View File

@ -698,7 +698,7 @@ public class MessageList
@Override
public void onResume() {
super.onResume();
if (mAccount != null && !mAccount.isAvailable(this)) {
onAccountUnavailable();
return;
@ -726,9 +726,9 @@ public class MessageList
}
} else {
// reread the selected date format preference in case it has changed
mMessageHelper.refresh();
// reread the selected date format preference in case it has changed
mMessageHelper.refresh();
new Thread() {
@Override
public void run() {
@ -1142,7 +1142,7 @@ public class MessageList
}
}
private void moveToSpamFolder(MessageInfoHolder holder){
private void moveToSpamFolder(MessageInfoHolder holder) {
if (!mController.isMoveCapable(holder.message)) {
Toast toast = Toast.makeText(this, R.string.move_copy_cannot_copy_unsynced_message, Toast.LENGTH_LONG);
toast.show();
@ -1286,31 +1286,31 @@ public class MessageList
switch (id) {
case DIALOG_MARK_ALL_AS_READ:
return ConfirmationDialog.create(this, id,
R.string.mark_all_as_read_dlg_title,
getString(R.string.mark_all_as_read_dlg_instructions_fmt,
mCurrentFolder.displayName),
R.string.okay_action,
R.string.cancel_action,
new Runnable() {
@Override
public void run() {
markAllAsRead();
}
});
R.string.mark_all_as_read_dlg_title,
getString(R.string.mark_all_as_read_dlg_instructions_fmt,
mCurrentFolder.displayName),
R.string.okay_action,
R.string.cancel_action,
new Runnable() {
@Override
public void run() {
markAllAsRead();
}
});
case R.id.dialog_confirm_spam:
return ConfirmationDialog.create(this, id,
R.string.dialog_confirm_spam_title,
R.string.dialog_confirm_spam_message,
R.string.dialog_confirm_spam_confirm_button,
R.string.dialog_confirm_spam_cancel_button,
new Runnable() {
@Override
public void run() {
moveToSpamFolder(mSelectedMessage);
// No further need for this reference
mSelectedMessage = null;
}
});
R.string.dialog_confirm_spam_title,
R.string.dialog_confirm_spam_message,
R.string.dialog_confirm_spam_confirm_button,
R.string.dialog_confirm_spam_cancel_button,
new Runnable() {
@Override
public void run() {
moveToSpamFolder(mSelectedMessage);
// No further need for this reference
mSelectedMessage = null;
}
});
}
return super.onCreateDialog(id);

View File

@ -932,29 +932,29 @@ public class MessageView extends K9Activity implements OnClickListener {
switch (id) {
case R.id.dialog_confirm_delete:
return ConfirmationDialog.create(this, id,
R.string.dialog_confirm_delete_title,
R.string.dialog_confirm_delete_message,
R.string.dialog_confirm_delete_confirm_button,
R.string.dialog_confirm_delete_cancel_button,
new Runnable() {
@Override
public void run() {
delete();
}
});
R.string.dialog_confirm_delete_title,
R.string.dialog_confirm_delete_message,
R.string.dialog_confirm_delete_confirm_button,
R.string.dialog_confirm_delete_cancel_button,
new Runnable() {
@Override
public void run() {
delete();
}
});
case R.id.dialog_confirm_spam:
return ConfirmationDialog.create(this, id,
R.string.dialog_confirm_spam_title,
R.string.dialog_confirm_spam_message,
R.string.dialog_confirm_spam_confirm_button,
R.string.dialog_confirm_spam_cancel_button,
new Runnable() {
@Override
public void run() {
refileMessage(mDstFolder);
mDstFolder = null;
}
});
R.string.dialog_confirm_spam_title,
R.string.dialog_confirm_spam_message,
R.string.dialog_confirm_spam_confirm_button,
R.string.dialog_confirm_spam_cancel_button,
new Runnable() {
@Override
public void run() {
refileMessage(mDstFolder);
mDstFolder = null;
}
});
case R.id.dialog_attachment_progress:
ProgressDialog d = new ProgressDialog(this);
d.setIndeterminate(true);

View File

@ -409,9 +409,9 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
} else {
String authType = ((SpinnerOption)mAuthTypeView.getSelectedItem()).label;
if (!authType.equalsIgnoreCase("plain")) {
userInfo = authType + ":" + userEnc + ":" + passwordEnc;
userInfo = authType + ":" + userEnc + ":" + passwordEnc;
} else {
userInfo = userEnc + ":" + passwordEnc;
userInfo = userEnc + ":" + passwordEnc;
}
}
URI uri = new URI(

View File

@ -182,15 +182,15 @@ public class Prefs extends K9PreferenceActivity {
mConfirmActions = (CheckBoxListPreference) findPreference(PREFERENCE_CONFIRM_ACTIONS);
mConfirmActions.setItems(new CharSequence[] {
getString(R.string.global_settings_confirm_action_delete),
getString(R.string.global_settings_confirm_action_spam),
getString(R.string.global_settings_confirm_action_mark_all_as_read)
});
getString(R.string.global_settings_confirm_action_delete),
getString(R.string.global_settings_confirm_action_spam),
getString(R.string.global_settings_confirm_action_mark_all_as_read)
});
mConfirmActions.setCheckedItems(new boolean[] {
K9.confirmDelete(),
K9.confirmSpam(),
K9.confirmMarkAllAsRead()
});
K9.confirmDelete(),
K9.confirmSpam(),
K9.confirmMarkAllAsRead()
});
mPrivacyMode = (CheckBoxPreference) findPreference(PREFERENCE_PRIVACY_MODE);
mPrivacyMode.setChecked(K9.keyguardPrivacy());

View File

@ -195,7 +195,7 @@ public abstract class Contacts {
public boolean hasContactPicker() {
if (mHasContactPicker == null) {
mHasContactPicker = (mContext.getPackageManager().
queryIntentActivities(contactPickerIntent(), 0).size() > 0);
queryIntentActivities(contactPickerIntent(), 0).size() > 0);
}
return mHasContactPicker;
}

View File

@ -239,11 +239,11 @@ public class ContactsSdk3_4 extends com.fsck.k9.helper.Contacts {
if (cursor.moveToFirst()) {
String emailId = cursor.getString(cursor.getColumnIndex(Contacts.People.PRIMARY_EMAIL_ID));
cursor2 = mContext.getContentResolver().query(
ContactMethods.CONTENT_EMAIL_URI,
new String[] { ContactMethods.DATA },
"contact_methods._id=?",
new String[] { emailId },
null);
ContactMethods.CONTENT_EMAIL_URI,
new String[] { ContactMethods.DATA },
"contact_methods._id=?",
new String[] { emailId },
null);
if (cursor2.moveToFirst()) {
email = cursor2.getString(0);

View File

@ -100,8 +100,8 @@ public class MessageHelper {
}
}
public void refresh() {
public void refresh() {
mDateFormat = DateFormatter.getDateFormat(mContext);
mTodayDateFormat = android.text.format.DateFormat.getTimeFormat(mContext);
}
mTodayDateFormat = android.text.format.DateFormat.getTimeFormat(mContext);
}
}

View File

@ -6,80 +6,80 @@ import com.fsck.k9.mail.filter.Base64;
import com.fsck.k9.mail.filter.Hex;
public class Authentication {
private static final String US_ASCII = "US-ASCII";
private static final String US_ASCII = "US-ASCII";
/**
* Computes the response for CRAM-MD5 authentication mechanism given the user credentials and
* the server-provided nonce.
*
* @param username The username.
* @param password The password.
* @param b64Nonce The nonce as base64-encoded string.
* @return The CRAM-MD5 response.
*
* @throws AuthenticationFailedException If something went wrong.
*
* @see Authentication#computeCramMd5Bytes(String, String, byte[])
*/
public static String computeCramMd5(String username, String password, String b64Nonce)
throws AuthenticationFailedException {
/**
* Computes the response for CRAM-MD5 authentication mechanism given the user credentials and
* the server-provided nonce.
*
* @param username The username.
* @param password The password.
* @param b64Nonce The nonce as base64-encoded string.
* @return The CRAM-MD5 response.
*
* @throws AuthenticationFailedException If something went wrong.
*
* @see Authentication#computeCramMd5Bytes(String, String, byte[])
*/
public static String computeCramMd5(String username, String password, String b64Nonce)
throws AuthenticationFailedException {
try {
byte[] b64NonceBytes = b64Nonce.getBytes(US_ASCII);
byte[] b64CRAM = computeCramMd5Bytes(username, password, b64NonceBytes);
return new String(b64CRAM, US_ASCII);
byte[] b64NonceBytes = b64Nonce.getBytes(US_ASCII);
byte[] b64CRAM = computeCramMd5Bytes(username, password, b64NonceBytes);
return new String(b64CRAM, US_ASCII);
} catch (AuthenticationFailedException e) {
throw e;
throw e;
} catch (Exception e) {
throw new AuthenticationFailedException("This shouldn't happen", e);
throw new AuthenticationFailedException("This shouldn't happen", e);
}
}
}
/**
* Computes the response for CRAM-MD5 authentication mechanism given the user credentials and
* the server-provided nonce.
*
* @param username The username.
* @param password The password.
* @param b64Nonce The nonce as base64-encoded byte array.
* @return The CRAM-MD5 response as byte array.
*
* @throws AuthenticationFailedException If something went wrong.
*
* @see <a href="https://tools.ietf.org/html/rfc2195">RFC 2195</a>
*/
public static byte[] computeCramMd5Bytes(String username, String password, byte[] b64Nonce)
throws AuthenticationFailedException {
/**
* Computes the response for CRAM-MD5 authentication mechanism given the user credentials and
* the server-provided nonce.
*
* @param username The username.
* @param password The password.
* @param b64Nonce The nonce as base64-encoded byte array.
* @return The CRAM-MD5 response as byte array.
*
* @throws AuthenticationFailedException If something went wrong.
*
* @see <a href="https://tools.ietf.org/html/rfc2195">RFC 2195</a>
*/
public static byte[] computeCramMd5Bytes(String username, String password, byte[] b64Nonce)
throws AuthenticationFailedException {
try {
byte[] nonce = Base64.decodeBase64(b64Nonce);
byte[] nonce = Base64.decodeBase64(b64Nonce);
byte[] secretBytes = password.getBytes(US_ASCII);
MessageDigest md = MessageDigest.getInstance("MD5");
if (secretBytes.length > 64) {
secretBytes = md.digest(secretBytes);
}
byte[] secretBytes = password.getBytes(US_ASCII);
MessageDigest md = MessageDigest.getInstance("MD5");
if (secretBytes.length > 64) {
secretBytes = md.digest(secretBytes);
}
byte[] ipad = new byte[64];
byte[] opad = new byte[64];
System.arraycopy(secretBytes, 0, ipad, 0, secretBytes.length);
System.arraycopy(secretBytes, 0, opad, 0, secretBytes.length);
for (int i = 0; i < ipad.length; i++) ipad[i] ^= 0x36;
for (int i = 0; i < opad.length; i++) opad[i] ^= 0x5c;
byte[] ipad = new byte[64];
byte[] opad = new byte[64];
System.arraycopy(secretBytes, 0, ipad, 0, secretBytes.length);
System.arraycopy(secretBytes, 0, opad, 0, secretBytes.length);
for (int i = 0; i < ipad.length; i++) ipad[i] ^= 0x36;
for (int i = 0; i < opad.length; i++) opad[i] ^= 0x5c;
md.update(ipad);
byte[] firstPass = md.digest(nonce);
md.update(ipad);
byte[] firstPass = md.digest(nonce);
md.update(opad);
byte[] result = md.digest(firstPass);
md.update(opad);
byte[] result = md.digest(firstPass);
String plainCRAM = username + " " + new String(Hex.encodeHex(result));
byte[] b64CRAM = Base64.encodeBase64(plainCRAM.getBytes(US_ASCII));
String plainCRAM = username + " " + new String(Hex.encodeHex(result));
byte[] b64CRAM = Base64.encodeBase64(plainCRAM.getBytes(US_ASCII));
return b64CRAM;
return b64CRAM;
} catch (Exception e) {
throw new AuthenticationFailedException("Something went wrong during CRAM-MD5 computation", e);
throw new AuthenticationFailedException("Something went wrong during CRAM-MD5 computation", e);
}
}
}
}

View File

@ -20,14 +20,13 @@ package com.fsck.k9.mail.filter;
* This code was copied from the Apache Commons project.
* The unnecessary parts have been left out.
*/
public class Hex
{
public class Hex {
/**
* Used building output as Hex
*/
private static final char[] DIGITS = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
/**
@ -43,15 +42,15 @@ public class Hex
int l = data.length;
char[] out = new char[l << 1];
char[] out = new char[l << 1];
// two characters form the hex value.
for (int i = 0, j = 0; i < l; i++) {
out[j++] = DIGITS[(0xF0 & data[i]) >>> 4 ];
out[j++] = DIGITS[ 0x0F & data[i] ];
}
// two characters form the hex value.
for (int i = 0, j = 0; i < l; i++) {
out[j++] = DIGITS[(0xF0 & data[i]) >>> 4 ];
out[j++] = DIGITS[ 0x0F & data[i] ];
}
return out;
return out;
}
}

View File

@ -1212,13 +1212,13 @@ public class MimeUtility {
* @see #MIME_TYPE_REPLACEMENT_MAP
*/
public static String canonicalizeMimeType(String mimeType) {
for (String[] mimeTypeMapEntry : MIME_TYPE_REPLACEMENT_MAP) {
if (mimeTypeMapEntry[0].equals(mimeType)) {
return mimeTypeMapEntry[1];
}
}
return mimeType;
}
for (String[] mimeTypeMapEntry : MIME_TYPE_REPLACEMENT_MAP) {
if (mimeTypeMapEntry[0].equals(mimeType)) {
return mimeTypeMapEntry[1];
}
}
return mimeType;
}
/**
* When viewing the attachment we want the MIME type to be as sensible as

View File

@ -362,7 +362,7 @@ public class ImapResponseParser {
}
return parseDate(value);
} catch (ParseException pe) {
throw new MessagingException("Unable to parse IMAP datetime '"+value+"' ", pe);
throw new MessagingException("Unable to parse IMAP datetime '" + value + "' ", pe);
}
}
@ -428,7 +428,7 @@ public class ImapResponseParser {
}
} catch (Exception e2) {
try {
synchronized (badDateTimeFormat2) {
synchronized (badDateTimeFormat2) {
return badDateTimeFormat2.parse(value);
}
} catch (Exception e3) {

View File

@ -2098,7 +2098,7 @@ public class ImapStore extends Store {
System.arraycopy(buf, 1, b64NonceTrim, 0, b64NonceLen - 2);
byte[] b64CRAM = Authentication.computeCramMd5Bytes(mSettings.getUsername(),
mSettings.getPassword(), b64NonceTrim);
mSettings.getPassword(), b64NonceTrim);
mOut.write(b64CRAM);
mOut.write(new byte[] { 0x0d, 0x0a });

View File

@ -1675,7 +1675,7 @@ public class LocalStore extends Store implements Serializable {
}
String encoded_name = EncoderUtil.encodeIfNecessary(name,
EncoderUtil.Usage.WORD_ENTITY, 7);
EncoderUtil.Usage.WORD_ENTITY, 7);
MimeBodyPart bp = new LocalAttachmentBodyPart(body, id);
bp.setHeader(MimeHeader.HEADER_CONTENT_TYPE,

View File

@ -91,11 +91,10 @@ public class Pop3Store extends Store {
try {
int userIndex = 0, passwordIndex = 1;
String[] userInfoParts = uri.getUserInfo().split(":");
if (userInfoParts.length > 2)
{
userIndex++;
passwordIndex++;
useCramMd5 = true;
if (userInfoParts.length > 2) {
userIndex++;
passwordIndex++;
useCramMd5 = true;
}
mUsername = URLDecoder.decode(userInfoParts[userIndex], "UTF-8");
if (userInfoParts.length > passwordIndex) {
@ -224,8 +223,7 @@ public class Pop3Store extends Store {
}
}
if (useCramMd5)
{
if (useCramMd5) {
try {
String b64Nonce = executeSimpleCommand("AUTH CRAM-MD5").replace("+ ", "");
@ -235,9 +233,7 @@ public class Pop3Store extends Store {
} catch (MessagingException me) {
throw new AuthenticationFailedException(null, me);
}
}
else
{
} else {
try {
executeSimpleCommand("USER " + mUsername);
executeSimpleCommand("PASS " + mPassword, true);

View File

@ -520,9 +520,9 @@ public class SmtpTransport extends Transport {
private void saslAuthCramMD5(String username, String password) throws MessagingException,
AuthenticationFailedException, IOException {
List<String> respList = executeSimpleCommand("AUTH CRAM-MD5");
List<String> respList = executeSimpleCommand("AUTH CRAM-MD5");
if (respList.size() != 1) {
throw new AuthenticationFailedException("Unable to negotiate CRAM-MD5");
throw new AuthenticationFailedException("Unable to negotiate CRAM-MD5");
}
String b64Nonce = respList.get(0);