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") // 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 // 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' || 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 $_GET['add-member'] = ''; // otherwise we give no Location header
return $this->PUT($options, 'POST'); return $this->PUT($options, 'POST');
@ -2027,7 +2028,7 @@ class CalDAV extends HTTP_WebDAV_Server
// check/handle Prefer: return-representation // check/handle Prefer: return-representation
if ($status[0] === '2' || $status === true) 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) if ($handler->check_return_representation($options, $id, $user) && (int)$status == 204)
{ {
$status = '200 Ok'; $status = '200 Ok';

View File

@ -273,7 +273,7 @@ class Account implements \ArrayAccess
$GLOBALS['egw_info']['user']['account_id'] && $GLOBALS['egw_info']['user']['account_id'] &&
(!isset($called_for) || $called_for == $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( $params = Credentials::from_session(
(!isset($called_for) ? array() : array('acc_smtp_auth_session' => false)) + $params, !isset($called_for) (!isset($called_for) ? array() : array('acc_smtp_auth_session' => false)) + $params, !isset($called_for)
) + $params; ) + $params;
@ -1594,9 +1594,10 @@ class Account implements \ArrayAccess
* @param boolean $smtp =false false: usable for IMAP, true: usable for SMTP * @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 $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 $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 * @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 try
{ {
@ -1606,7 +1607,7 @@ class Account implements \ArrayAccess
{ {
if (!$params['acc_smtp_host'] || !$params['acc_smtp_port']) continue; if (!$params['acc_smtp_host'] || !$params['acc_smtp_port']) continue;
// check requirement of session, which is not available in async service! // 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 empty($GLOBALS['egw_info']['user']['account_id'])) // happens during login when notifying about blocked accounts
{ {
if ($params['acc_smtp_auth_session']) continue; 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']).'!'); throw new Api\Exception\WrongParameter("Unknown data[acc_imap_logintype]=".array2string($data['acc_imap_logintype']).'!');
} }
$password = base64_decode(Api\Cache::getSession('phpgwapi', 'password')); $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'] : $realname = !$set_identity || !empty($data['ident_realname']) ? $data['ident_realname'] :
($GLOBALS['egw_info']['user']['account_fullname'] ?? null); ($GLOBALS['egw_info']['user']['account_fullname'] ?? null);
$email = !$set_identity || !empty($data['ident_email']) ? $data['ident_email'] : $email = !$set_identity || !empty($data['ident_email']) ? $data['ident_email'] :

View File

@ -2936,10 +2936,10 @@ class mail_compose
return $messageUid; return $messageUid;
} }
function send($_formData) function send($_formData, int $_acc_id=null)
{ {
$mail_bo = $this->mail_bo; $mail_bo = $this->mail_bo;
$mail = new Api\Mailer($mail_bo->profileID); $mail = new Api\Mailer($_acc_id ?: $mail_bo->profileID);
$messageIsDraft = false; $messageIsDraft = false;
$this->sessionData['mailaccount'] = $_formData['mailaccount']; $this->sessionData['mailaccount'] = $_formData['mailaccount'];
@ -3073,7 +3073,12 @@ class mail_compose
// we use the sentFolder settings of the choosen mailaccount // we use the sentFolder settings of the choosen mailaccount
// sentFolder is account specific // sentFolder is account specific
$changeProfileOnSentFolderNeeded = false; $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']); $this->changeProfile($_formData['mailaccount']);
//error_log(__METHOD__.__LINE__.'#'.$this->mail_bo->profileID.'<->'.$mail_bo->profileID.'#'); //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); ], self::JSON_RESPONSE_OPTIONS);
return true; return true;
} }
$acc_id = Api\Mail\Account::read_identity($ident_id)['acc_id'];
$compose = new \mail_compose($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([ $preset = array_filter([
'mailaccount' => $acc_id, 'mailaccount' => $acc_id,
'mailidentity' => $ident_id, 'mailidentity' => $ident_id,
'identity' => null, 'identity' => null,
'add_signature' => true, // add signature in send, independent what preference says 'add_signature' => true, // add signature in send, independent what preference says
]+$preset); ]+$preset);
if ($compose->send($preset)) if ($compose->send($preset, $acc_id))
{ {
header('Content-Type: application/json'); header('Content-Type: application/json');
echo json_encode([ echo json_encode(array_filter([
'status' => 200, 'status' => 200,
'warning' => $warning ?? null,
'message' => 'Mail successful sent', 'message' => 'Mail successful sent',
//'data' => $preset, //'data' => $preset,
], self::JSON_RESPONSE_OPTIONS); ]), self::JSON_RESPONSE_OPTIONS);
return true; return true;
} }
throw new \Exception($compose->error_info); throw new \Exception($compose->error_info);