WIP Mail REST API: enable direct sending of mails with token authentication / no password not allowing to save mail to Sent folder

This commit is contained in:
ralf 2023-07-07 10:49:58 +02:00
parent d46f8f4a4e
commit 2bd5fd5601
5 changed files with 38 additions and 13 deletions

View File

@ -1501,7 +1501,8 @@ class CalDAV extends HTTP_WebDAV_Server
// for some reason OS X Addressbook (CFNetwork user-agent) uses now (DAV:add-member given with collection URL+"?add-member")
// POST to the collection URL plus a UID like name component (like for regular PUT) to create new entrys
if (isset($_GET['add-member']) || Handler::get_agent() == 'cfnetwork' ||
substr($options['path'], -1) === '/' && self::isJSON())
// addressbook has not implemented a POST handler, therefore we have to call the PUT handler
preg_match('#^(/[^/]+)?/addressbook(-[^/]+)?/$', $options['path']) && self::isJSON())
{
$_GET['add-member'] = ''; // otherwise we give no Location header
return $this->PUT($options, 'POST');
@ -2027,7 +2028,7 @@ class CalDAV extends HTTP_WebDAV_Server
// check/handle Prefer: return-representation
if ($status[0] === '2' || $status === true)
{
// we can NOT use 204 No content (forbidds a body) with return=representation, therefore we need to use 200 Ok instead!
// we can NOT use 204 No content (forbids a body) with return=representation, therefore we need to use 200 Ok instead!
if ($handler->check_return_representation($options, $id, $user) && (int)$status == 204)
{
$status = '200 Ok';

View File

@ -273,7 +273,7 @@ class Account implements \ArrayAccess
$GLOBALS['egw_info']['user']['account_id'] &&
(!isset($called_for) || $called_for == $GLOBALS['egw_info']['user']['account_id']))
{
// get usename/password from current user, let it overwrite credentials for all/no session
// get username/password from current user, let it overwrite credentials for all/no session
$params = Credentials::from_session(
(!isset($called_for) ? array() : array('acc_smtp_auth_session' => false)) + $params, !isset($called_for)
) + $params;
@ -1594,9 +1594,10 @@ class Account implements \ArrayAccess
* @param boolean $smtp =false false: usable for IMAP, true: usable for SMTP
* @param boolean $return_id =false true: return acc_id, false return account object
* @param boolean $log_no_default =true true: error_log if no default found, false be silent
* @param boolean $user_context =true false: we have no user context, need a smtp-only account or one without password
* @return Account|int|null
*/
static function get_default($smtp=false, $return_id=false, $log_no_default=true)
static function get_default($smtp=false, $return_id=false, $log_no_default=true, $user_context=true)
{
try
{
@ -1606,7 +1607,7 @@ class Account implements \ArrayAccess
{
if (!$params['acc_smtp_host'] || !$params['acc_smtp_port']) continue;
// check requirement of session, which is not available in async service!
if (isset($GLOBALS['egw_info']['flags']['async-service']) ||
if (!$user_context || isset($GLOBALS['egw_info']['flags']['async-service']) ||
empty($GLOBALS['egw_info']['user']['account_id'])) // happens during login when notifying about blocked accounts
{
if ($params['acc_smtp_auth_session']) continue;

View File

@ -324,6 +324,11 @@ class Credentials
throw new Api\Exception\WrongParameter("Unknown data[acc_imap_logintype]=".array2string($data['acc_imap_logintype']).'!');
}
$password = base64_decode(Api\Cache::getSession('phpgwapi', 'password'));
// if session password is a token, do NOT use it, but also do NOT throw, just return NULL for the password(s)
if (Api\Auth\Token::isToken($password))
{
$password = null;
}
$realname = !$set_identity || !empty($data['ident_realname']) ? $data['ident_realname'] :
($GLOBALS['egw_info']['user']['account_fullname'] ?? null);
$email = !$set_identity || !empty($data['ident_email']) ? $data['ident_email'] :

View File

@ -2936,10 +2936,10 @@ class mail_compose
return $messageUid;
}
function send($_formData)
function send($_formData, int $_acc_id=null)
{
$mail_bo = $this->mail_bo;
$mail = new Api\Mailer($mail_bo->profileID);
$mail = new Api\Mailer($_acc_id ?: $mail_bo->profileID);
$messageIsDraft = false;
$this->sessionData['mailaccount'] = $_formData['mailaccount'];
@ -3073,7 +3073,12 @@ class mail_compose
// we use the sentFolder settings of the choosen mailaccount
// sentFolder is account specific
$changeProfileOnSentFolderNeeded = false;
if ($_formData['serverID']!=$_formData['mailaccount'])
if ($this->mailPreferences['sendOptions'] === 'send_only')
{
// no need to check for Sent folder
$sentFolder = 'none';
}
elseif ($_formData['serverID']!=$_formData['mailaccount'])
{
$this->changeProfile($_formData['mailaccount']);
//error_log(__METHOD__.__LINE__.'#'.$this->mail_bo->profileID.'<->'.$mail_bo->profileID.'#');

View File

@ -94,22 +94,35 @@ class ApiHandler extends Api\CalDAV\Handler
], self::JSON_RESPONSE_OPTIONS);
return true;
}
$compose = new \mail_compose($acc_id=Api\Mail\Account::read_identity($ident_id)['acc_id']);
$acc_id = Api\Mail\Account::read_identity($ident_id)['acc_id'];
$mail_account = Api\Mail\Account::read($acc_id);
// check if the mail-account requires a user-context / password and then just send the mail with an smtp-only account NOT saving to Sent folder
if (empty($mail_account->acc_imap_password) || $mail_account->acc_smtp_auth_session && empty($mail_account->acc_smtp_password))
{
$acc_id = Api\Mail\Account::get_default(true, true, true, false);
$compose = new \mail_compose($acc_id);
$compose->mailPreferences['sendOptions'] = 'send_only';
$warning = 'Mail NOT saved to Sent folder, as no user password';
}
else
{
$compose = new \mail_compose($acc_id);
}
$preset = array_filter([
'mailaccount' => $acc_id,
'mailidentity' => $ident_id,
'identity' => null,
'add_signature' => true, // add signature in send, independent what preference says
]+$preset);
if ($compose->send($preset))
if ($compose->send($preset, $acc_id))
{
header('Content-Type: application/json');
echo json_encode([
echo json_encode(array_filter([
'status' => 200,
'warning' => $warning ?? null,
'message' => 'Mail successful sent',
//'data' => $preset,
], self::JSON_RESPONSE_OPTIONS);
]), self::JSON_RESPONSE_OPTIONS);
return true;
}
throw new \Exception($compose->error_info);