1
0
Fork 0
mirror of synced 2024-06-29 19:50:26 +12:00

Merge remote-tracking branch 'origin/feat-git-integration' into feat-git-integration-no-hook

This commit is contained in:
Jake Barnby 2023-08-29 11:59:44 -04:00
commit 84177b0fb0
No known key found for this signature in database
GPG key ID: C437A8CC85B96E9C
17 changed files with 359 additions and 256 deletions

2
.gitmodules vendored
View file

@ -1,4 +1,4 @@
[submodule "app/console"]
path = app/console
url = https://github.com/appwrite/console
branch = 1.4.x
branch = main

View file

@ -671,11 +671,6 @@ return [
'description' => 'Provided SMTP config is invalid. Please check the configured values and try again.',
'code' => 400,
],
Exception::PROJECT_SMTP_CONFIG_NOT_FOUND => [
'name' => Exception::PROJECT_SMTP_CONFIG_NOT_FOUND,
'description' => 'SMTP configuration on project is missing. Please configure a custom SMTP server to enable custom email templates.',
'code' => 404,
],
Exception::PROJECT_TEMPLATE_DEFAULT_DELETION => [
'name' => Exception::PROJECT_TEMPLATE_DEFAULT_DELETION,
'description' => 'You can\'t delete default template. If you are trying to reset your template changes, you can ignore this error as it\'s already been reset.',

View file

@ -54,16 +54,6 @@
<div style="max-width:650px; word-wrap: break-wrod; overflow-wrap: break-word;
word-break: break-all; margin:0 auto;">
<table style="margin-top: 32px">
<tr>
<td>
<h1>
{{subject}}
</h1>
</td>
</tr>
</table>
<table style="margin-top: 40px">
<tr>
<td>
{{body}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
Subproject commit 51aa80cc80e83a41466bb353ccdff0e0e37d492f
Subproject commit 0534cf0a65f4d8766926cf391d345cc0ad1d3c20

View file

@ -1091,33 +1091,60 @@ App::post('/v1/account/sessions/magic-url')
$url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['userId' => $user->getId(), 'secret' => $loginSecret, 'expire' => $expire, 'project' => $project->getId()]);
$url = Template::unParseURL($url);
$from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $project->getAttribute('name'));
$body = $locale->getText("emails.magicSession.body");
$subject = $locale->getText("emails.magicSession.subject");
$smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false;
$customTemplate = $project->getAttribute('templates', [])['email.magicSession-' . $locale->default] ?? [];
if ($smtpEnabled && !empty($customTemplate)) {
$body = $customTemplate['message'] ?? '';
$subject = $customTemplate['subject'] ?? $subject;
$from = $customTemplate['senderName'] ?? $from;
$smtp = $project->getAttribute('smtp', []);
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl');
$message->setParam('{{body}}', $body);
$body = $message->render();
$smtp = $project->getAttribute('smtp', []);
$smtpEnabled = $smtp['enabled'] ?? false;
$senderEmail = App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM);
$senderName = App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server');
$replyTo = "";
if ($smtpEnabled) {
if (!empty($smtp['senderEmail'])) {
$senderEmail = $smtp['senderEmail'];
}
if (!empty($smtp['senderName'])) {
$senderName = $smtp['senderName'];
}
if (!empty($smtp['replyTo'])) {
$replyTo = $smtp['replyTo'];
}
$mails
->setSmtpHost($smtp['host'] ?? '')
->setSmtpPort($smtp['port'] ?? '')
->setSmtpUsername($smtp['username'] ?? '')
->setSmtpPassword($smtp['password'] ?? '')
->setSmtpSecure($smtp['secure'] ?? '')
->setSmtpReplyTo($customTemplate['replyTo'] ?? '')
->setSmtpSenderEmail($customTemplate['senderEmail'] ?? '')
->setSmtpSenderName($customTemplate['senderName'] ?? '');
} else {
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl');
$message->setParam('{{body}}', $body);
$body = $message->render();
->setSmtpSecure($smtp['secure'] ?? '');
}
if (!empty($customTemplate)) {
if (!empty($customTemplate['senderEmail'])) {
$senderEmail = $customTemplate['senderEmail'];
}
if (!empty($customTemplate['senderName'])) {
$senderName = $customTemplate['senderName'];
}
if (!empty($customTemplate['replyTo'])) {
$replyTo = $customTemplate['replyTo'];
}
$body = $customTemplate['message'] ?? '';
$subject = $customTemplate['subject'] ?? $subject;
}
$mails
->setSmtpReplyTo($replyTo)
->setSmtpSenderEmail($senderEmail)
->setSmtpSenderName($senderName);
$emailVariables = [
'subject' => $subject,
'hello' => $locale->getText("emails.magicSession.hello"),
@ -1138,7 +1165,6 @@ App::post('/v1/account/sessions/magic-url')
->setSubject($subject)
->setBody($body)
->setVariables($emailVariables)
->setFrom($from)
->setRecipient($user->getAttribute('email'))
->trigger()
;
@ -2522,33 +2548,60 @@ App::post('/v1/account/recovery')
$url = Template::unParseURL($url);
$projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]');
$from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $projectName);
$body = $locale->getText("emails.recovery.body");
$subject = $locale->getText("emails.recovery.subject");
$smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false;
$customTemplate = $project->getAttribute('templates', [])['email.recovery-' . $locale->default] ?? [];
if ($smtpEnabled && !empty($customTemplate)) {
$body = $customTemplate['message'];
$subject = $customTemplate['subject'] ?? $subject;
$from = $customTemplate['senderName'] ?? $from;
$smtp = $project->getAttribute('smtp', []);
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl');
$message->setParam('{{body}}', $body);
$body = $message->render();
$smtp = $project->getAttribute('smtp', []);
$smtpEnabled = $smtp['enabled'] ?? false;
$senderEmail = App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM);
$senderName = App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server');
$replyTo = "";
if ($smtpEnabled) {
if (!empty($smtp['senderEmail'])) {
$senderEmail = $smtp['senderEmail'];
}
if (!empty($smtp['senderName'])) {
$senderName = $smtp['senderName'];
}
if (!empty($smtp['replyTo'])) {
$replyTo = $smtp['replyTo'];
}
$mails
->setSmtpHost($smtp['host'] ?? '')
->setSmtpPort($smtp['port'] ?? '')
->setSmtpUsername($smtp['username'] ?? '')
->setSmtpPassword($smtp['password'] ?? '')
->setSmtpSecure($smtp['secure'] ?? '')
->setSmtpReplyTo($customTemplate['replyTo'] ?? '')
->setSmtpSenderEmail($customTemplate['senderEmail'] ?? '')
->setSmtpSenderName($customTemplate['senderName'] ?? '');
} else {
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl');
$message->setParam('{{body}}', $body);
$body = $message->render();
->setSmtpSecure($smtp['secure'] ?? '');
}
if (!empty($customTemplate)) {
if (!empty($customTemplate['senderEmail'])) {
$senderEmail = $customTemplate['senderEmail'];
}
if (!empty($customTemplate['senderName'])) {
$senderName = $customTemplate['senderName'];
}
if (!empty($customTemplate['replyTo'])) {
$replyTo = $customTemplate['replyTo'];
}
$body = $customTemplate['message'] ?? '';
$subject = $customTemplate['subject'] ?? $subject;
}
$mails
->setSmtpReplyTo($replyTo)
->setSmtpSenderEmail($senderEmail)
->setSmtpSenderName($senderName);
$emailVariables = [
'subject' => $subject,
'hello' => $locale->getText("emails.recovery.hello"),
@ -2571,7 +2624,6 @@ App::post('/v1/account/recovery')
->setName($profile->getAttribute('name'))
->setBody($body)
->setVariables($emailVariables)
->setFrom($from)
->setSubject($subject)
->trigger();
;
@ -2747,33 +2799,60 @@ App::post('/v1/account/verification')
$url = Template::unParseURL($url);
$projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]');
$from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $projectName);
$body = $locale->getText("emails.verification.body");
$subject = $locale->getText("emails.verification.subject");
$smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false;
$customTemplate = $project->getAttribute('templates', [])['email.verification-' . $locale->default] ?? [];
if ($smtpEnabled && !empty($customTemplate)) {
$body = $customTemplate['message'] ?? '';
$subject = $customTemplate['subject'] ?? $subject;
$from = $customTemplate['senderName'] ?? $from;
$smtp = $project->getAttribute('smtp', []);
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl');
$message->setParam('{{body}}', $body);
$body = $message->render();
$smtp = $project->getAttribute('smtp', []);
$smtpEnabled = $smtp['enabled'] ?? false;
$senderEmail = App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM);
$senderName = App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server');
$replyTo = "";
if ($smtpEnabled) {
if (!empty($smtp['senderEmail'])) {
$senderEmail = $smtp['senderEmail'];
}
if (!empty($smtp['senderName'])) {
$senderName = $smtp['senderName'];
}
if (!empty($smtp['replyTo'])) {
$replyTo = $smtp['replyTo'];
}
$mails
->setSmtpHost($smtp['host'] ?? '')
->setSmtpPort($smtp['port'] ?? '')
->setSmtpUsername($smtp['username'] ?? '')
->setSmtpPassword($smtp['password'] ?? '')
->setSmtpSecure($smtp['secure'] ?? '')
->setSmtpReplyTo($customTemplate['replyTo'] ?? '')
->setSmtpSenderEmail($customTemplate['senderEmail'] ?? '')
->setSmtpSenderName($customTemplate['senderName'] ?? '');
} else {
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl');
$message->setParam('{{body}}', $body);
$body = $message->render();
->setSmtpSecure($smtp['secure'] ?? '');
}
if (!empty($customTemplate)) {
if (!empty($customTemplate['senderEmail'])) {
$senderEmail = $customTemplate['senderEmail'];
}
if (!empty($customTemplate['senderName'])) {
$senderName = $customTemplate['senderName'];
}
if (!empty($customTemplate['replyTo'])) {
$replyTo = $customTemplate['replyTo'];
}
$body = $customTemplate['message'] ?? '';
$subject = $customTemplate['subject'] ?? $subject;
}
$mails
->setSmtpReplyTo($replyTo)
->setSmtpSenderEmail($senderEmail)
->setSmtpSenderName($senderName);
$emailVariables = [
'subject' => $subject,
'hello' => $locale->getText("emails.verification.hello"),
@ -2794,7 +2873,6 @@ App::post('/v1/account/verification')
->setSubject($subject)
->setBody($body)
->setVariables($emailVariables)
->setFrom($from)
->setRecipient($user->getAttribute('email'))
->setName($user->getAttribute('name') ?? '')
->trigger()

View file

@ -29,6 +29,10 @@ App::get('/v1/console/variables')
->label('sdk.response.model', Response::MODEL_CONSOLE_VARIABLES)
->inject('response')
->action(function (Response $response) {
$isDomainEnabled = !empty(App::getEnv('_APP_DOMAIN', ''))
&& !empty(App::getEnv('_APP_DOMAIN_TARGET', ''))
&& App::getEnv('_APP_DOMAIN', '') !== 'localhost'
&& App::getEnv('_APP_DOMAIN_TARGET', '') !== 'localhost';
$isVcsEnabled = !empty(App::getEnv('_APP_VCS_GITHUB_APP_NAME', ''))
&& !empty(App::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY', ''))
@ -44,6 +48,7 @@ App::get('/v1/console/variables')
'_APP_FUNCTIONS_SIZE_LIMIT' => +App::getEnv('_APP_FUNCTIONS_SIZE_LIMIT'),
'_APP_USAGE_STATS' => App::getEnv('_APP_USAGE_STATS'),
'_APP_VCS_ENABLED' => $isVcsEnabled,
'_APP_DOMAIN_ENABLED' => $isDomainEnabled,
'_APP_ASSISTANT_ENABLED' => $isAssistantEnabled
]);

View file

@ -61,7 +61,7 @@ App::post('/v1/projects')
->param('projectId', '', new ProjectId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, and hyphen. Can\'t start with a special char. Max length is 36 chars.')
->param('name', null, new Text(128), 'Project name. Max length: 128 chars.')
->param('teamId', '', new UID(), 'Team unique ID.')
->param('region', App::getEnv('_APP_REGION', 'default'), new Whitelist(array_keys(array_filter(Config::getParam('regions'), fn($config) => !$config['disabled']))), 'Project Region.', true)
->param('region', App::getEnv('_APP_REGION', 'default'), new Whitelist(array_keys(array_filter(Config::getParam('regions'), fn ($config) => !$config['disabled']))), 'Project Region.', true)
->param('description', '', new Text(256), 'Project description. Max length: 256 chars.', true)
->param('logo', '', new Text(1024), 'Project logo.', true)
->param('url', '', new URL(), 'Project URL.', true)
@ -436,17 +436,17 @@ App::patch('/v1/projects/:projectId')
}
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project
->setAttribute('name', $name)
->setAttribute('description', $description)
->setAttribute('logo', $logo)
->setAttribute('url', $url)
->setAttribute('legalName', $legalName)
->setAttribute('legalCountry', $legalCountry)
->setAttribute('legalState', $legalState)
->setAttribute('legalCity', $legalCity)
->setAttribute('legalAddress', $legalAddress)
->setAttribute('legalTaxId', $legalTaxId)
->setAttribute('search', implode(' ', [$projectId, $name])));
->setAttribute('name', $name)
->setAttribute('description', $description)
->setAttribute('logo', $logo)
->setAttribute('url', $url)
->setAttribute('legalName', $legalName)
->setAttribute('legalCountry', $legalCountry)
->setAttribute('legalState', $legalState)
->setAttribute('legalCity', $legalCity)
->setAttribute('legalAddress', $legalAddress)
->setAttribute('legalTaxId', $legalTaxId)
->setAttribute('search', implode(' ', [$projectId, $name])));
$response->dynamic($project, Response::MODEL_PROJECT);
});
@ -479,14 +479,14 @@ App::patch('/v1/projects/:projectId/team')
}
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project
->setAttribute('teamId', $teamId)
->setAttribute('$permissions', [
Permission::read(Role::team(ID::custom($teamId))),
Permission::update(Role::team(ID::custom($teamId), 'owner')),
Permission::update(Role::team(ID::custom($teamId), 'developer')),
Permission::delete(Role::team(ID::custom($teamId), 'owner')),
Permission::delete(Role::team(ID::custom($teamId), 'developer')),
]));
->setAttribute('teamId', $teamId)
->setAttribute('$permissions', [
Permission::read(Role::team(ID::custom($teamId))),
Permission::update(Role::team(ID::custom($teamId), 'owner')),
Permission::update(Role::team(ID::custom($teamId), 'developer')),
Permission::delete(Role::team(ID::custom($teamId), 'owner')),
Permission::delete(Role::team(ID::custom($teamId), 'developer')),
]));
$response->dynamic($project, Response::MODEL_PROJECT);
});
@ -502,7 +502,7 @@ App::patch('/v1/projects/:projectId/service')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_PROJECT)
->param('projectId', '', new UID(), 'Project unique ID.')
->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), fn($element) => $element['optional'])), true), 'Service name.')
->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), fn ($element) => $element['optional'])), true), 'Service name.')
->param('status', null, new Boolean(), 'Service status.')
->inject('response')
->inject('dbForConsole')
@ -544,7 +544,7 @@ App::patch('/v1/projects/:projectId/service/all')
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
$allServices = array_keys(array_filter(Config::getParam('services'), fn($element) => $element['optional']));
$allServices = array_keys(array_filter(Config::getParam('services'), fn ($element) => $element['optional']));
$services = [];
foreach ($allServices as $service) {
@ -843,8 +843,7 @@ App::delete('/v1/projects/:projectId')
$deletes
->setType(DELETE_TYPE_DOCUMENT)
->setDocument($project)
;
->setDocument($project);
if (!$dbForConsole->deleteDocument('projects', $projectId)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove project from DB');
@ -1022,8 +1021,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
->setAttribute('url', $url)
->setAttribute('security', $security)
->setAttribute('httpUser', $httpUser)
->setAttribute('httpPass', $httpPass)
;
->setAttribute('httpPass', $httpPass);
$dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook);
$dbForConsole->deleteCachedDocument('projects', $project->getId());
@ -1262,8 +1260,7 @@ App::put('/v1/projects/:projectId/keys/:keyId')
$key
->setAttribute('name', $name)
->setAttribute('scopes', $scopes)
->setAttribute('expire', $expire)
;
->setAttribute('expire', $expire);
$dbForConsole->updateDocument('keys', $key->getId(), $key);
@ -1465,8 +1462,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId')
->setAttribute('name', $name)
->setAttribute('key', $key)
->setAttribute('store', $store)
->setAttribute('hostname', $hostname)
;
->setAttribute('hostname', $hostname);
$dbForConsole->updateDocument('platforms', $platform->getId(), $platform);
@ -1525,15 +1521,17 @@ App::patch('/v1/projects/:projectId/smtp')
->label('sdk.response.model', Response::MODEL_PROJECT)
->param('projectId', '', new UID(), 'Project unique ID.')
->param('enabled', false, new Boolean(), 'Enable custom SMTP service')
->param('sender', '', new Email(), 'SMTP sender email')
->param('host', '', new HostName(), 'SMTP server host name')
->param('port', null, new Integer(), 'SMTP server port')
->param('username', null, new Text(0), 'SMTP server username')
->param('password', null, new Text(0), 'SMTP server password')
->param('senderName', '', new Text(255, 0), 'Name of the email sender', true)
->param('senderEmail', '', new Email(), 'Email of the sender', true)
->param('replyTo', '', new Email(), 'Reply to email', true)
->param('host', '', new HostName(), 'SMTP server host name', true)
->param('port', 587, new Integer(), 'SMTP server port', true)
->param('username', '', new Text(0), 'SMTP server username', true)
->param('password', '', new Text(0), 'SMTP server password', true)
->param('secure', '', new WhiteList(['tls'], true), 'Does SMTP server use secure connection', true)
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, bool $enabled, string $sender, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForConsole) {
->action(function (string $projectId, bool $enabled, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForConsole) {
$project = $dbForConsole->getDocument('projects', $projectId);
@ -1541,36 +1539,64 @@ App::patch('/v1/projects/:projectId/smtp')
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
// validate SMTP settings
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Username = $username;
$mail->Password = $password;
$mail->Host = $host;
$mail->Port = $port;
$mail->SMTPSecure = $secure;
$mail->SMTPAutoTLS = false;
$mail->Timeout = 5;
try {
$valid = $mail->SmtpConnect();
if (!$valid) {
throw new Exception('Connection is not valid.');
// Ensure required params for when enabling SMTP
if ($enabled) {
if (empty($senderName)) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Sender name is required when enabling SMTP.');
} elseif (empty($senderEmail)) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Sender email is required when enabling SMTP.');
} elseif (empty($host)) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Host is required when enabling SMTP.');
} elseif (empty($port)) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Port is required when enabling SMTP.');
} elseif (empty($username)) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Username is required when enabling SMTP.');
} elseif (empty($password)) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Password is required when enabling SMTP.');
}
} catch (Throwable $error) {
throw new Exception(Exception::PROJECT_SMTP_CONFIG_INVALID, 'Could not connect to SMTP server: ' . $error->getMessage());
}
$smtp = [
'enabled' => $enabled,
'sender' => $sender,
'host' => $host,
'port' => $port,
'username' => $username,
'password' => $password,
'secure' => $secure,
];
// validate SMTP settings
if ($enabled) {
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Username = $username;
$mail->Password = $password;
$mail->Host = $host;
$mail->Port = $port;
$mail->SMTPSecure = $secure;
$mail->SMTPAutoTLS = false;
$mail->Timeout = 5;
try {
$valid = $mail->SmtpConnect();
if (!$valid) {
throw new Exception('Connection is not valid.');
}
} catch (Throwable $error) {
throw new Exception(Exception::PROJECT_SMTP_CONFIG_INVALID, 'Could not connect to SMTP server: ' . $error->getMessage());
}
}
// Save SMTP settings
if ($enabled) {
$smtp = [
'enabled' => $enabled,
'senderName' => $senderName,
'senderEmail' => $senderEmail,
'replyTo' => $replyTo,
'host' => $host,
'port' => $port,
'username' => $username,
'password' => $password,
'secure' => $secure,
];
} else {
$smtp = [
'enabled' => false
];
}
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('smtp', $smtp));
@ -1589,7 +1615,7 @@ App::get('/v1/projects/:projectId/templates/sms/:type/:locale')
->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE)
->param('projectId', '', new UID(), 'Project unique ID.')
->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type')
->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) {
@ -1607,7 +1633,7 @@ App::get('/v1/projects/:projectId/templates/sms/:type/:locale')
if (is_null($template)) {
$template = [
'message' => Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl')->render(),
'message' => Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl')->render(),
];
}
@ -1629,7 +1655,7 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale')
->label('sdk.response.model', Response::MODEL_EMAIL_TEMPLATE)
->param('projectId', '', new UID(), 'Project unique ID.')
->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type')
->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) {
@ -1656,13 +1682,11 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale')
->setParam('{{direction}}', $localeObj->getText('settings.direction'));
$message = $message->render();
$from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($localeObj->getText('emails.sender'), $project->getAttribute('name'));
$from = empty($from) ? \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')) : $from;
$template = [
'message' => $message,
'subject' => $localeObj->getText('emails.' . $type . '.subject'),
'senderEmail' => App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', ''),
'senderName' => $from
'senderEmail' => '',
'senderName' => ''
];
}
@ -1684,7 +1708,7 @@ App::patch('/v1/projects/:projectId/templates/sms/:type/:locale')
->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE)
->param('projectId', '', new UID(), 'Project unique ID.')
->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type')
->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
->param('message', '', new Text(0), 'Template message')
->inject('response')
->inject('dbForConsole')
@ -1698,8 +1722,6 @@ App::patch('/v1/projects/:projectId/templates/sms/:type/:locale')
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
// TODO: Ensure SMS is enabled on project
$templates = $project->getAttribute('templates', []);
$templates['sms.' . $type . '-' . $locale] = [
'message' => $message
@ -1726,15 +1748,15 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale')
->label('sdk.response.model', Response::MODEL_PROJECT)
->param('projectId', '', new UID(), 'Project unique ID.')
->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type')
->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
->param('senderName', '', new Text(255), 'Name of the email sender')
->param('senderEmail', '', new Email(), 'Email of the sender')
->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
->param('subject', '', new Text(255), 'Email Subject')
->param('message', '', new Text(0), 'Template message')
->param('senderName', '', new Text(255, 0), 'Name of the email sender', true)
->param('senderEmail', '', new Email(), 'Email of the sender', true)
->param('replyTo', '', new Email(), 'Reply to email', true)
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, string $type, string $locale, string $senderName, string $senderEmail, string $subject, string $message, string $replyTo, Response $response, Database $dbForConsole) {
->action(function (string $projectId, string $type, string $locale, string $subject, string $message, string $senderName, string $senderEmail, string $replyTo, Response $response, Database $dbForConsole) {
$project = $dbForConsole->getDocument('projects', $projectId);
@ -1742,11 +1764,6 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale')
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
$smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false;
if (!$smtpEnabled) {
throw new Exception(Exception::PROJECT_SMTP_CONFIG_NOT_FOUND);
}
$templates = $project->getAttribute('templates', []);
$templates['email.' . $type . '-' . $locale] = [
'senderName' => $senderName,
@ -1781,7 +1798,7 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale')
->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE)
->param('projectId', '', new UID(), 'Project unique ID.')
->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type')
->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) {
@ -1824,7 +1841,7 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale')
->label('sdk.response.model', Response::MODEL_EMAIL_TEMPLATE)
->param('projectId', '', new UID(), 'Project unique ID.')
->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type')
->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) {

View file

@ -543,33 +543,60 @@ App::post('/v1/teams/:teamId/memberships')
if (!empty($email)) {
$projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]');
$from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $projectName);
$body = $locale->getText("emails.invitation.body");
$subject = \sprintf($locale->getText("emails.invitation.subject"), $team->getAttribute('name'), $projectName);
$smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false;
$customTemplate = $project->getAttribute('templates', [])['email.invitation-' . $locale->default] ?? [];
if ($smtpEnabled && !empty($customTemplate)) {
$body = Template::fromString($customTemplate['message'] ?? '');
$subject = $customTemplate['subject'] ?? $subject;
$from = $customTemplate['senderName'] ?? $from;
$smtp = $project->getAttribute('smtp', []);
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl');
$message->setParam('{{body}}', $body);
$body = $message->render();
$smtp = $project->getAttribute('smtp', []);
$smtpEnabled = $smtp['enabled'] ?? false;
$senderEmail = App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM);
$senderName = App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server');
$replyTo = "";
if ($smtpEnabled) {
if (!empty($smtp['senderEmail'])) {
$senderEmail = $smtp['senderEmail'];
}
if (!empty($smtp['senderName'])) {
$senderName = $smtp['senderName'];
}
if (!empty($smtp['replyTo'])) {
$replyTo = $smtp['replyTo'];
}
$mails
->setSmtpHost($smtp['host'] ?? '')
->setSmtpPort($smtp['port'] ?? '')
->setSmtpUsername($smtp['username'] ?? '')
->setSmtpPassword($smtp['password'] ?? '')
->setSmtpSecure($smtp['secure'] ?? '')
->setSmtpReplyTo($customTemplate['replyTo'] ?? '')
->setSmtpSenderEmail($customTemplate['senderEmail'] ?? '')
->setSmtpSenderName($customTemplate['senderName'] ?? '');
} else {
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl');
$message->setParam('{{body}}', $body);
$body = $message->render();
->setSmtpSecure($smtp['secure'] ?? '');
}
if (!empty($customTemplate)) {
if (!empty($customTemplate['senderEmail'])) {
$senderEmail = $customTemplate['senderEmail'];
}
if (!empty($customTemplate['senderName'])) {
$senderName = $customTemplate['senderName'];
}
if (!empty($customTemplate['replyTo'])) {
$replyTo = $customTemplate['replyTo'];
}
$body = $customTemplate['message'] ?? '';
$subject = $customTemplate['subject'] ?? $subject;
}
$mails
->setSmtpReplyTo($replyTo)
->setSmtpSenderEmail($senderEmail)
->setSmtpSenderName($senderName);
$emailVariables = [
'owner' => $user->getAttribute('name'),
'team' => $team->getAttribute('name'),
@ -591,7 +618,6 @@ App::post('/v1/teams/:teamId/memberships')
$mails
->setSubject($subject)
->setBody($body)
->setFrom($from)
->setRecipient($invitee->getAttribute('email'))
->setName($invitee->getAttribute('name'))
->setVariables($emailVariables)

View file

@ -38,7 +38,6 @@ class MailsV1 extends Worker
$name = $this->args['name'];
$body = $this->args['body'];
$variables = $this->args['variables'];
$from = $this->args['from'];
$body = Template::fromFile(__DIR__ . '/../config/locale/templates/email-base.tpl');
@ -62,6 +61,11 @@ class MailsV1 extends Worker
$mail->Body = $body;
$mail->AltBody = \strip_tags($body);
$mail->setFrom($smtp['senderEmail'], $smtp['senderName']);
if (!empty($smtp['replyTo'])) {
$mail->addReplyTo($smtp['replyTo'], $smtp['senderName']);
}
try {
$mail->send();
} catch (\Exception $error) {
@ -88,12 +92,6 @@ class MailsV1 extends Worker
$mail->SMTPAutoTLS = false;
$mail->CharSet = 'UTF-8';
$from = \urldecode($smtp['senderName'] ?? App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server'));
$email = $smtp['senderEmail'] ?? App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM);
$mail->setFrom($email, $from);
$mail->addReplyTo($email, $from);
$mail->isHTML(true);
return $mail;

View file

@ -49,7 +49,7 @@
"utopia-php/cache": "0.8.*",
"utopia-php/cli": "0.15.*",
"utopia-php/config": "0.2.*",
"utopia-php/database": "0.42.*",
"utopia-php/database": "0.43.*",
"utopia-php/domains": "0.3.*",
"utopia-php/dsn": "0.1.*",
"utopia-php/framework": "0.30.0",

98
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "7cb5852653a858c1846543914c20f87f",
"content-hash": "a60b9a87c757ec717c0f7c9c7abd1051",
"packages": [
{
"name": "adhocore/jwt",
@ -1846,16 +1846,16 @@
},
{
"name": "symfony/polyfill-php80",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
"shasum": ""
},
"require": {
@ -1864,7 +1864,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1909,7 +1909,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0"
},
"funding": [
{
@ -1925,27 +1925,27 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "utopia-php/abuse",
"version": "0.31.0",
"version": "0.31.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/abuse.git",
"reference": "d771c2c8d7d1237b1d04b5bf57b07a9b4736e627"
"reference": "b2ad372d1070f55f9545cb811b6ed2d40094e6dd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/d771c2c8d7d1237b1d04b5bf57b07a9b4736e627",
"reference": "d771c2c8d7d1237b1d04b5bf57b07a9b4736e627",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/b2ad372d1070f55f9545cb811b6ed2d40094e6dd",
"reference": "b2ad372d1070f55f9545cb811b6ed2d40094e6dd",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-pdo": "*",
"php": ">=8.0",
"utopia-php/database": "0.42.*"
"utopia-php/database": "0.43.*"
},
"require-dev": {
"laravel/pint": "1.5.*",
@ -1972,9 +1972,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/abuse/issues",
"source": "https://github.com/utopia-php/abuse/tree/0.31.0"
"source": "https://github.com/utopia-php/abuse/tree/0.31.1"
},
"time": "2023-08-11T01:17:15+00:00"
"time": "2023-08-29T11:07:46+00:00"
},
{
"name": "utopia-php/analytics",
@ -2024,21 +2024,21 @@
},
{
"name": "utopia-php/audit",
"version": "0.33.0",
"version": "0.33.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/audit.git",
"reference": "6fb82331c58c66cbdb8a419314a687fcb18a1d22"
"reference": "c117e8e9ce4e3e1b369e8b5b55b2d6ab3138eadd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/6fb82331c58c66cbdb8a419314a687fcb18a1d22",
"reference": "6fb82331c58c66cbdb8a419314a687fcb18a1d22",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/c117e8e9ce4e3e1b369e8b5b55b2d6ab3138eadd",
"reference": "c117e8e9ce4e3e1b369e8b5b55b2d6ab3138eadd",
"shasum": ""
},
"require": {
"php": ">=8.0",
"utopia-php/database": "0.42.*"
"utopia-php/database": "0.43.*"
},
"require-dev": {
"laravel/pint": "1.5.*",
@ -2065,9 +2065,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/audit/issues",
"source": "https://github.com/utopia-php/audit/tree/0.33.0"
"source": "https://github.com/utopia-php/audit/tree/0.33.1"
},
"time": "2023-08-11T01:17:28+00:00"
"time": "2023-08-29T11:07:40+00:00"
},
{
"name": "utopia-php/cache",
@ -2220,16 +2220,16 @@
},
{
"name": "utopia-php/database",
"version": "0.42.3",
"version": "0.43.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "2d52ce8ac92436cd51c36cff2ec7bfdf00c44189"
"reference": "fb96fc6c94d5efcd43913c34bece62daba76a5e9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/2d52ce8ac92436cd51c36cff2ec7bfdf00c44189",
"reference": "2d52ce8ac92436cd51c36cff2ec7bfdf00c44189",
"url": "https://api.github.com/repos/utopia-php/database/zipball/fb96fc6c94d5efcd43913c34bece62daba76a5e9",
"reference": "fb96fc6c94d5efcd43913c34bece62daba76a5e9",
"shasum": ""
},
"require": {
@ -2271,9 +2271,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/0.42.3"
"source": "https://github.com/utopia-php/database/tree/0.43.0"
},
"time": "2023-08-25T06:18:31+00:00"
"time": "2023-08-29T10:18:39+00:00"
},
{
"name": "utopia-php/domains",
@ -5736,16 +5736,16 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"shasum": ""
},
"require": {
@ -5760,7 +5760,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -5798,7 +5798,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0"
},
"funding": [
{
@ -5814,20 +5814,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
"reference": "42292d99c55abe617799667f454222c54c60e229"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
"reference": "42292d99c55abe617799667f454222c54c60e229",
"shasum": ""
},
"require": {
@ -5842,7 +5842,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -5881,7 +5881,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
},
"funding": [
{
@ -5897,7 +5897,7 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-07-28T09:04:16+00:00"
},
{
"name": "textalk/websocket",
@ -6000,16 +6000,16 @@
},
{
"name": "twig/twig",
"version": "v3.7.0",
"version": "v3.7.1",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "5cf942bbab3df42afa918caeba947f1b690af64b"
"reference": "a0ce373a0ca3bf6c64b9e3e2124aca502ba39554"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/5cf942bbab3df42afa918caeba947f1b690af64b",
"reference": "5cf942bbab3df42afa918caeba947f1b690af64b",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/a0ce373a0ca3bf6c64b9e3e2124aca502ba39554",
"reference": "a0ce373a0ca3bf6c64b9e3e2124aca502ba39554",
"shasum": ""
},
"require": {
@ -6019,7 +6019,7 @@
},
"require-dev": {
"psr/container": "^1.0|^2.0",
"symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0"
"symfony/phpunit-bridge": "^5.4.9|^6.3"
},
"type": "library",
"autoload": {
@ -6055,7 +6055,7 @@
],
"support": {
"issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v3.7.0"
"source": "https://github.com/twigphp/Twig/tree/v3.7.1"
},
"funding": [
{
@ -6067,7 +6067,7 @@
"type": "tidelift"
}
],
"time": "2023-07-26T07:16:09+00:00"
"time": "2023-08-28T11:09:02+00:00"
}
],
"aliases": [],

View file

@ -8,7 +8,6 @@ use Utopia\Database\Document;
class Mail extends Event
{
protected string $recipient = '';
protected string $from = '';
protected string $name = '';
protected string $subject = '';
protected string $body = '';
@ -66,29 +65,6 @@ class Mail extends Event
return $this->recipient;
}
/**
* Sets from for the mail event.
*
* @param string $from
* @return self
*/
public function setFrom(string $from): self
{
$this->from = $from;
return $this;
}
/**
* Returns from for mail event.
*
* @return string
*/
public function getFrom(): string
{
return $this->from;
}
/**
* Sets body for the mail event.
*
@ -342,7 +318,6 @@ class Mail extends Event
public function trigger(): string|bool
{
return Resque::enqueue($this->queue, $this->class, [
'from' => $this->from,
'recipient' => $this->recipient,
'name' => $this->name,
'subject' => $this->subject,

View file

@ -189,7 +189,6 @@ class Exception extends \Exception
public const PROJECT_KEY_EXPIRED = 'project_key_expired';
public const PROJECT_SMTP_CONFIG_INVALID = 'project_smtp_config_invalid';
public const PROJECT_SMTP_CONFIG_NOT_FOUND = 'project_smtp_config_not_found';
public const PROJECT_TEMPLATE_DEFAULT_DELETION = 'project_template_default_deletion';

View file

@ -40,6 +40,12 @@ class ConsoleVariables extends Model
'default' => false,
'example' => true,
])
->addRule('_APP_DOMAIN_ENABLED', [
'type' => self::TYPE_BOOLEAN,
'description' => 'Defines if main domain is configured. If so, custom domains can be created.',
'default' => false,
'example' => true,
])
->addRule('_APP_ASSISTANT_ENABLED', [
'type' => self::TYPE_BOOLEAN,
'description' => 'Defines if AI assistant is enabled.',

View file

@ -173,12 +173,24 @@ class Project extends Model
'example' => false,
'array' => false
])
->addRule('smtpSender', [
->addRule('smtpSenderName', [
'type' => self::TYPE_STRING,
'description' => 'SMTP sender name',
'default' => '',
'example' => 'John Appwrite',
])
->addRule('smtpSenderEmail', [
'type' => self::TYPE_STRING,
'description' => 'SMTP sender email',
'default' => '',
'example' => 'john@appwrite.io',
])
->addRule('smtpReplyTo', [
'type' => self::TYPE_STRING,
'description' => 'SMTP reply to email',
'default' => '',
'example' => 'support@appwrite.io',
])
->addRule('smtpHost', [
'type' => self::TYPE_STRING,
'description' => 'SMTP server host name',
@ -277,7 +289,9 @@ class Project extends Model
// SMTP
$smtp = $document->getAttribute('smtp', []);
$document->setAttribute('smtpEnabled', $smtp['enabled'] ?? false);
$document->setAttribute('smtpSender', $smtp['sender'] ?? '');
$document->setAttribute('smtpSenderEmail', $smtp['senderEmail'] ?? '');
$document->setAttribute('smtpSenderName', $smtp['senderName'] ?? '');
$document->setAttribute('smtpReplyTo', $smtp['replyTo'] ?? '');
$document->setAttribute('smtpHost', $smtp['host'] ?? '');
$document->setAttribute('smtpPort', $smtp['port'] ?? '');
$document->setAttribute('smtpUsername', $smtp['username'] ?? '');