MojErr DeleteAccountCommand::GetAccountInfoResponse(MojObject& response, MojErr err)
{
	CommandTraceFunction();

	try {
		ResponseToException(response, err);

		MojObject result;
		err = response.getRequired("result", result);
		ErrorToException(err);

		MojString templateId;
		bool hasTemplateId = false;
		err = result.get(ImapAccountAdapter::TEMPLATEID, templateId, hasTemplateId);
		ErrorToException(err);

		if(hasTemplateId) {
			if(templateId == "com.palm.yahoo") { // FIXME use constant
				m_isYahoo = true;
			}
		}

		DeleteAccount();
	} CATCH_AS_FAILURE

	return MojErrNone;
}
MojErr SmtpSyncOutboxCommand::GetOutboxEmailsResponse(MojObject &response, MojErr err)
{
	try {
		ResponseToException(response, err);
	
		try {
			ErrorToException(err);

			BOOST_FOREACH(const MojObject& email, DatabaseAdapter::GetResultsIterators(response)) {
				m_emailsToSend.push_back(email);
			}

			if(DatabaseAdapter::GetNextPage(response, m_outboxPage)) {
				// Get more emails
				GetSomeOutboxEmails();
			} else {
				MojLogInfo(m_log, "Found %d emails in outbox", m_emailsToSend.size());

				m_emailIt = m_emailsToSend.begin();

				m_didSomething = false;

				SendNextEmail();
			}
		} catch(std::exception& e) {
			HandleException(e, __func__);
		} catch(...) {
			HandleException(__func__);
		}

	} catch (std::exception & e) {
MojErr SmtpAccountDisableCommand::DeleteAccountWatchResponse(MojObject& response, MojErr err)
{
	MojLogInfo(m_log, "SmtpAccountDisable replying");

	try {
		if(err) {
			if(err == ENOENT) {
				MojLogWarning(m_log, "account watch activity doesn't exist");
			} else {
				ResponseToException(response, err);
			}
		}

		m_msg->replySuccess();
		Complete();
	} catch (const std::exception& e) {
		m_msg->replyError(err, e.what());
		Failure(e);
	} catch (...) {
		MojString error;
		error.format("uncaught exception in %s", __PRETTY_FUNCTION__);
		m_msg->replyError(MojErrInternal, error.data());
		Failure(MailException("unknown exception in cancelling activities response", __FILE__, __LINE__));
	}
	return MojErrNone;
}
MojErr SmtpAccountDisableCommand::DeleteOutboxWatchResponse(MojObject& response, MojErr err)
{
	MojLogInfo(m_log, "SmtpAccountDisable removing outbox watch");

	try {
		if(err) {
			if(err == ENOENT) {
				MojLogWarning(m_log, "outbox watch activity doesn't exist");
			} else {
				ResponseToException(response, err);
			}
		}

		MojObject payload;
		payload.put("activityName", m_accountWatchActivityName);

		m_client.SendRequest(m_deleteAccountWatchResponseSlot, "com.palm.activitymanager", "cancel", payload);
	} catch (const std::exception& e) {
		m_msg->replyError(err, e.what());
		Failure(e);
	} catch (...) {
		MojString error;
		error.format("uncaught exception in %s", __PRETTY_FUNCTION__);
		m_msg->replyError(MojErrInternal, error.data());
		Failure(MailException("unknown exception in cancelling activities response", __FILE__, __LINE__));
	}

	return MojErrNone;
}
MojErr SmtpSyncOutboxCommand::GotAccount(MojObject &response, MojErr err)
{
	try {
		ResponseToException(response, err);
		MojLogInfo(m_log, "GotAccount, response elided");
	
		try {
			MojObject accountObj;
			DatabaseAdapter::GetOneResult(response, accountObj);
                                                                                                                                        
			err = accountObj.getRequired(EmailAccountAdapter::OUTBOX_FOLDERID, m_folderId);
			ErrorToException(err);

			// FIXME _ prefix is reserved for MojoDB internal properties
			err = accountObj.getRequired("_revSmtp", m_accountRev);
			ErrorToException(err);
			
			MojLogInfo(m_log, "Sync GotAccount, _revSmtp=%lld", m_accountRev);
			
			boost::shared_ptr<SmtpAccount> smtpAccountObj(new SmtpAccount());
			
			MojObject nothing;
			
			SmtpAccountAdapter::GetSmtpAccount(nothing, accountObj, smtpAccountObj);
			
			m_error = SmtpSession::SmtpError(smtpAccountObj->GetSmtpError());
			
			FindOutgoingFolder();

		} catch (const std::exception& e) {
	
			MojLogInfo(m_log, "No account data, erroring out: %s", e.what());
			
			// We must log an error if we cannot find the
			// appropriate outbox folder id, so that in the case
			// of a missing folder, we'll disconnect any
			// potentially left-over watches, and not come back
			// up until the account watches trigger us to update
			// and try again.
			
			m_error.errorCode = MailError::SMTP_CONFIG_UNAVAILABLE;
			m_error.errorOnAccount = true;
			m_error.errorOnEmail = false;
			m_error.internalError = "Unable to retrieve account data for SMTP account";
			m_error.errorText = "";
			
			SmtpSyncOutboxCommand::CompleteAndUpdateActivities();
			
			return MojErrNone;
		}

	} catch (std::exception & e) {
		HandleException(e, __func__);
	} catch (...) {
		HandleException(__func__);
	}
	
	return MojErrNone;
}
MojErr SmtpAccountEnableCommand::CreateSmtpConfigWatchResponse(MojObject& response, MojErr err)
{
	try {
		ResponseToException(response, err);

		CreateOutboxWatch();
	} catch(const std::exception& e) {
		Failure(e);
	}

	return MojErrNone;
}
MojErr SmtpSyncOutboxCommand::FindOutgoingFolderResponse(MojObject &response, MojErr err)
{
	try {
		ResponseToException(response, err);
		MojLogInfo(m_log, "FindOutgoingFolderResponse, response elided");
	
		try {
			MojObject folder;
			DatabaseAdapter::GetOneResult(response, folder);

			m_retryDelay.clear();
			folder.get("smtpRetryDelay", m_retryDelay);
			ErrorToException(err);
                
			m_retryDelayNew = m_retryDelay;

			MojString json;
			m_retryDelay.toJson(json);
			MojLogInfo(m_log, "got retry delay %s", json.data());
			
			UpdateAccountWatchActivity();
		
		} catch(...) {
			MojLogInfo(m_log, "No outgoing folder, erroring out");
		
			// We must log an error if we cannot find the
			// appropriate outbox folder id, so that in the case
			// of a missing folder, we'll disconnect any
			// potentially left-over watches, and not come back
			// up until the account watches trigger us to update
			// and try again.
			
			m_error.errorCode = MailError::SMTP_OUTBOX_UNAVAILABLE;
			m_error.errorOnAccount = true;
			m_error.errorOnEmail = false;
			m_error.internalError = "Unable to establish outbox folder associated with SMTP account";
			m_error.errorText = "";
			SmtpSyncOutboxCommand::CompleteAndUpdateActivities();
			
			return MojErrNone;
		}

	} catch (std::exception & e) {
		HandleException(e, __func__);
	} catch (...) {
		HandleException(__func__);
	}
        
	return MojErrNone;
}
MojErr PopAccountUpdateCommand::NotifySmtpResponse(MojObject& response, MojErr err)
{
	CommandTraceFunction();

	try {
		ResponseToException(response, err);
	} catch(const std::exception& e) {
		// log and ignore error
		MojLogError(m_log, "error calling SMTP credentialsChanged: %s", e.what());
	}

	Done();

	return MojErrNone;
}
MojErr DeleteAccountCommand::SmtpAccountDeletedResponse(MojObject& response, MojErr err)
{
	CommandTraceFunction();

	try {
		ResponseToException(response, err);

		if(m_isYahoo) {
			DeleteYahooAccount();
		} else {
			Done();
		}
	} CATCH_AS_FAILURE

	return MojErrNone;
}
MojErr SmtpSyncOutboxCommand::SetSyncStatusResponse(MojObject& response, MojErr err)
{
	try {
		ResponseToException(response, err);
		
		MojLogInfo(m_log, "SmtpSyncOutboxCommand::SetSyncStatusResponse sync status created");

		StartSync();
	} catch (std::exception& e) {
		HandleException(e, __func__);
	} catch (...) {
		HandleException(__func__);
	}

	return MojErrNone;
}
MojErr SmtpSyncOutboxCommand::ClearSyncStatusResponse(MojObject& response, MojErr err)
{
	try {
		ResponseToException(response, err);

		m_client.GetTempDatabaseInterface().CreateSyncStatus(m_setSyncStatusSlot, m_accountId, m_folderId, SyncStateAdapter::STATE_INCREMENTAL_SYNC);

		MojLogInfo(m_log, "SmtpSyncOutboxCommand::ClearSyncStatusResponse old SMTP sync status cleared, creating new sync status");
	} catch (std::exception& e) {
		HandleException(e, __func__);
	} catch (...) {
		HandleException(__func__);
	}

	return MojErrNone;
}
MojErr AuthYahooCommand::GetYahooCookiesSlot(MojObject& response, MojErr err)
{
	MojLogTrace(m_log);
	try {
		ResponseToException(response, err);

		MojObject object;
		err = response.getRequired("tCookie", m_tCookie);
		ErrorToException(err);
	
		err = response.getRequired("yCookie", m_yCookie);
		ErrorToException(err);
	
	} catch (const std::exception& e) {
		MojLogInfo(m_log, "Failed to retrieve Yahoo cookies, failing login: %s", e.what());
		
		// FIXME: We should possibly try to decode and pass along a specific error
		
		SmtpSession::SmtpError error;
		error.errorCode = MailError::ACCOUNT_UNAVAILABLE;
		error.errorOnAccount = true;
		error.internalError = std::string("Unable to retrieve yahoo cookies: ") + e.what();
		m_session.AuthYahooFailure(error);
		Complete();
		
		return MojErrNone;
	} catch (...) {
		MojLogInfo(m_log, "Failed to retrieve Yahoo cookies, failing login: unknown exception");

		// FIXME: We should possibly try to decode and pass along a specific error

		SmtpSession::SmtpError error;
		error.errorCode = MailError::ACCOUNT_UNAVAILABLE;
		error.errorOnAccount = true;
		error.internalError = "Unable to retrieve yahoo cookies: unknown exception";
		m_session.AuthYahooFailure(error);
		Complete();

		return MojErrNone;
	}

	m_state = State_SendingYCookie;
	WriteCommand();
	
	return MojErrNone;
}
MojErr SmtpSyncOutboxCommand::ResetErrorResponse(MojObject& response, MojErr err)
{
	try {
		ResponseToException(response, err);

		MojString json;
		response.toJson(json);		
		MojLogInfo(m_log, "SmtpSyncOutboxCommand::ResetErrorResponse got response to updating error status, payload=%s", json.data());
	
		GetOutboxEmails();

	} catch (std::exception & e) {
		HandleException(e, __func__);
	} catch (...) {
		HandleException(__func__);
	}

	return MojErrNone;
}
MojErr DeleteAccountCommand::YahooAccountDeletedResponse(MojObject& response, MojErr err)
{
	CommandTraceFunction();

	try {
		if(err) {
			try {
				ResponseToException(response, err);
			} catch(const std::exception& e) {
				// Ignore error
				MojLogWarning(m_log, "error cleaning up Yahoo service data: %s", e.what());
			}
		}

		Done();
	} CATCH_AS_FAILURE

	return MojErrNone;
}
MojErr SmtpSyncOutboxCommand::CreateAccountWatchResponse(MojObject& response, MojErr err)
{
	try {
		ResponseToException(response, err);

		MojString json;
		err = response.toJson(json);
		MojErrCheck(err);
		MojLogInfo(m_log, "response from activitymanager on updating watch activity: %s", json.data());

		CheckErrorCodes();

	} catch (std::exception & e) {
		HandleException(e, __func__);
	} catch (...) {
		HandleException(__func__);
	}

	return MojErrNone;
}
MojErr SmtpAccountEnableCommand::GetMailAccountResponse(MojObject& response, MojErr err)
{
	try {
		ResponseToException(response, err);

		MojObject account;

		DatabaseAdapter::GetOneResult(response, account);

		err = account.getRequired(DatabaseAdapter::REV, m_accountRev);
		ErrorToException(err);

		err = account.getRequired(EmailAccountAdapter::OUTBOX_FOLDERID, m_outboxFolderId);
		ErrorToException(err);

		CreateSmtpConfigWatch();
	} catch(const std::exception& e) {
		Failure(e);
	}

	return MojErrNone;
}
MojErr DeleteActivitiesCommand::GetActivityListResponse(MojObject& response, MojErr err)
{
	CommandTraceFunction();

	try {
		ResponseToException(response, err);

		MojObject activities;
		err = response.getRequired("activities", activities);
		ErrorToException(err);

		MojString creatorIdSubstring;
		err = creatorIdSubstring.assign("com.palm.imap");
		ErrorToException(err);

		BOOST_FOREACH(const MojObject& activity, DatabaseAdapter::GetArrayIterators(activities)) {
			MojObject activityId;
			err = activity.getRequired("activityId", activityId);
			ErrorToException(err);

			MojString name;
			err = activity.getRequired("name", name);
			ErrorToException(err);

			MojString creator;
			err = activity.getRequired("creator", creator);
			ErrorToException(err);

			// Check that the accountId and creator (com.palm.imap) are in the activity fields
			if(creator.find(creatorIdSubstring.data(), 0) != MojInvalidIndex
			&& ShouldDeleteActivity(activity)) {
				fprintf(stderr, "preparing to delete activity id=%s name=%s, creator=%s\n",
					AsJsonString(activityId).c_str(), name.data(), creator.data());
				m_deleteIds.push(activityId);
			}
		}

		DeleteActivities();
	} CATCH_AS_FAILURE
MojErr SaveEmailCommand::FileCacheObjectInserted(MojObject &response, MojErr err)
{
	try {
		ResponseToException(response, err);

		MojLogDebug(m_log, "successfully created file cache entry");

		MojString pathName;
		err = response.getRequired("pathName", pathName);
		ErrorToException(err);

		MojObject& part = *m_partsIt++;
		part.putString(EmailSchema::Part::PATH, pathName);

		WriteToFileCache(part, pathName);
	} catch(const std::exception& e) {
		Error(e);
	} catch(...) {
		Error( MailException("unknown", __FILE__, __LINE__) );
	}
	
	return MojErrNone;
}
MojErr SaveEmailCommand::GetAccountResponse(MojObject &response, MojErr err)
{
	try {
		ResponseToException(response, err);

		MojObject accountObj;
		DatabaseAdapter::GetOneResult(response, accountObj);

		const char* folderPropertyName = m_isDraft ? EmailAccountAdapter::DRAFTS_FOLDERID : EmailAccountAdapter::OUTBOX_FOLDERID;
		err = accountObj.getRequired(folderPropertyName, m_folderId);
		ErrorToException(err);

		MojLogDebug(m_log, "preparing to save email to folderId %s", AsJsonString(m_folderId).c_str());

		PrepareParts();
	} catch(const std::exception& e) {
		Error(e);
	} catch(...) {
		Error( MailException("unknown", __FILE__, __LINE__) );
	}
	
	return MojErrNone;
}
MojErr SaveEmailCommand::PutDone(MojObject &response, MojErr err)
{
	try {
		ResponseToException(response, err);

		MojObject results;
		err = response.getRequired("results", results);
		ErrorToException(err);

		MojObject put;
		results.at(0, put);

		MojObject emailId;
		err = put.getRequired("id", emailId);
		ErrorToException(err);

		// create response that contains emailId
		MojObject response;
		
		err = response.putBool(MojServiceMessage::ReturnValueKey, true);
		ErrorToException(err);
		        
		err = response.put(DatabaseAdapter::ID, emailId);
		ErrorToException(err);

		err = m_message->reply(response);
		ErrorToException(err);

		m_client.CommandComplete(this);
	} catch(const std::exception& e) {
		Error(e);
	} catch(...) {
		Error( MailException("unknown", __FILE__, __LINE__) );
	}

	return MojErrNone;
}
MojErr SmtpSendMailCommand::GetEmailResponse(MojObject& response, MojErr err)
{
	try {
		ResponseToException(response, err);

		MojString json;
		response.toJson(json);
		MojLogInfo(m_log, "got Email response");
		MojLogDebug(m_log, "Response: %s", json.data());

		// check the database result first
		ErrorToException(err);

		MojObject results;
		err = response.getRequired(_T("results"), results);
		ErrorToException(err);
		
		if(results.size() == 0) {
			throw MailException("email not found", __FILE__, __LINE__);
		}
		
		// There should only be one email for a given id
		assert(results.size() == 1);

		MojObject emailObj;
		bool hasObject = results.at(0, emailObj);
		if(!hasObject) {
			throw MailException("error getting email from results", __FILE__, __LINE__);
		}

		EmailAdapter::ParseDatabaseObject(emailObj, m_email);
		
		m_toAddress.clear();
		
		if (m_email.GetTo()) {
			for (EmailAddressList::iterator i = m_email.GetTo()->begin();
				i != m_email.GetTo()->end();
				i++)
				m_toAddress.push_back((*i)->GetAddress());
		}
		if (m_email.GetCc()) {
			for (EmailAddressList::iterator i = m_email.GetCc()->begin();
				i != m_email.GetCc()->end();
				i++)
				m_toAddress.push_back((*i)->GetAddress());
		}
		if (m_email.GetBcc()) {
			for (EmailAddressList::iterator i = m_email.GetBcc()->begin();
				i != m_email.GetBcc()->end();
				i++)
				m_toAddress.push_back((*i)->GetAddress());
		}
		
		m_toIdx = 0;

		// FIXME: Subscribe to file cache to pin cache contents
		
		CalculateEmailSize();
		
	} catch (const std::exception& e) {
		HandleException(e, __func__, __FILE__, __LINE__);
	} catch (...) {
		HandleUnknownException();
	}

	return MojErrNone;
}