Changeset View
Changeset View
Standalone View
Standalone View
src/applications/metamta/storage/PhabricatorMetaMTAMail.php
| Show First 20 Lines • Show All 429 Lines • ▼ Show 20 Lines | try { | ||||
| $is_threaded = (bool)idx($params, 'thread-id'); | $is_threaded = (bool)idx($params, 'thread-id'); | ||||
| $reply_to_name = idx($params, 'reply-to-name', ''); | $reply_to_name = idx($params, 'reply-to-name', ''); | ||||
| unset($params['reply-to-name']); | unset($params['reply-to-name']); | ||||
| $add_cc = array(); | $add_cc = array(); | ||||
| $add_to = array(); | $add_to = array(); | ||||
| // Only try to use preferences if everything is multiplexed, so we | |||||
| // get consistent behavior. | |||||
| $use_prefs = self::shouldMultiplexAllMail(); | |||||
| $prefs = null; | |||||
| if ($use_prefs) { | |||||
| // If multiplexing is enabled, some recipients will be in "Cc" | // If multiplexing is enabled, some recipients will be in "Cc" | ||||
| // rather than "To". We'll move them to "To" later (or supply a | // rather than "To". We'll move them to "To" later (or supply a | ||||
| // dummy "To") but need to look for the recipient in either the | // dummy "To") but need to look for the recipient in either the | ||||
| // "To" or "Cc" fields here. | // "To" or "Cc" fields here. | ||||
| $target_phid = head(idx($params, 'to', array())); | $target_phid = head(idx($params, 'to', array())); | ||||
| if (!$target_phid) { | if (!$target_phid) { | ||||
| $target_phid = head(idx($params, 'cc', array())); | $target_phid = head(idx($params, 'cc', array())); | ||||
| } | } | ||||
| if ($target_phid) { | $preferences = $this->loadPreferences($target_phid); | ||||
| $user = id(new PhabricatorUser())->loadOneWhere( | |||||
| 'phid = %s', | |||||
| $target_phid); | |||||
| if ($user) { | |||||
| $prefs = $user->loadPreferences(); | |||||
| } | |||||
| } | |||||
| } | |||||
| foreach ($params as $key => $value) { | foreach ($params as $key => $value) { | ||||
| switch ($key) { | switch ($key) { | ||||
| case 'raw-from': | case 'raw-from': | ||||
| list($from_email, $from_name) = $value; | list($from_email, $from_name) = $value; | ||||
| $mailer->setFrom($from_email, $from_name); | $mailer->setFrom($from_email, $from_name); | ||||
| break; | break; | ||||
| case 'from': | case 'from': | ||||
| ▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | try { | ||||
| $attachment->getFilename(), | $attachment->getFilename(), | ||||
| $attachment->getMimeType()); | $attachment->getMimeType()); | ||||
| } | } | ||||
| break; | break; | ||||
| case 'subject': | case 'subject': | ||||
| $subject = array(); | $subject = array(); | ||||
| if ($is_threaded) { | if ($is_threaded) { | ||||
| $add_re = PhabricatorEnv::getEnvConfig('metamta.re-prefix'); | if ($this->shouldAddRePrefix($preferences)) { | ||||
| if ($prefs) { | |||||
| $add_re = $prefs->getPreference( | |||||
| PhabricatorUserPreferences::PREFERENCE_RE_PREFIX, | |||||
| $add_re); | |||||
| } | |||||
| if ($add_re) { | |||||
| $subject[] = 'Re:'; | $subject[] = 'Re:'; | ||||
| } | } | ||||
| } | } | ||||
| $subject[] = trim(idx($params, 'subject-prefix')); | $subject[] = trim(idx($params, 'subject-prefix')); | ||||
| $vary_prefix = idx($params, 'vary-subject-prefix'); | $vary_prefix = idx($params, 'vary-subject-prefix'); | ||||
| if ($vary_prefix != '') { | if ($vary_prefix != '') { | ||||
| $use_subject = PhabricatorEnv::getEnvConfig( | if ($this->shouldVarySubject($preferences)) { | ||||
| 'metamta.vary-subjects'); | |||||
| if ($prefs) { | |||||
| $use_subject = $prefs->getPreference( | |||||
| PhabricatorUserPreferences::PREFERENCE_VARY_SUBJECT, | |||||
| $use_subject); | |||||
| } | |||||
| if ($use_subject) { | |||||
| $subject[] = $vary_prefix; | $subject[] = $vary_prefix; | ||||
| } | } | ||||
| } | } | ||||
| $subject[] = $value; | $subject[] = $value; | ||||
| $mailer->setSubject(implode(' ', array_filter($subject))); | $mailer->setSubject(implode(' ', array_filter($subject))); | ||||
| break; | break; | ||||
| Show All 38 Lines | try { | ||||
| $body = id(new PhutilUTF8StringTruncator()) | $body = id(new PhutilUTF8StringTruncator()) | ||||
| ->setMaximumBytes($max) | ->setMaximumBytes($max) | ||||
| ->truncateString($body); | ->truncateString($body); | ||||
| $body .= "\n"; | $body .= "\n"; | ||||
| $body .= pht('(This email was truncated at %d bytes.)', $max); | $body .= pht('(This email was truncated at %d bytes.)', $max); | ||||
| } | } | ||||
| $mailer->setBody($body); | $mailer->setBody($body); | ||||
| $html_emails = true; | $html_emails = $this->shouldSendHTML($preferences); | ||||
| if ($use_prefs && $prefs) { | |||||
| $html_emails = $prefs->getPreference( | |||||
| PhabricatorUserPreferences::PREFERENCE_HTML_EMAILS, | |||||
| $html_emails); | |||||
| } | |||||
| if ($html_emails && isset($params['html-body'])) { | if ($html_emails && isset($params['html-body'])) { | ||||
| $mailer->setHTMLBody($params['html-body']); | $mailer->setHTMLBody($params['html-body']); | ||||
| } | } | ||||
| // Pass the headers to the mailer, then save the state so we can show | // Pass the headers to the mailer, then save the state so we can show | ||||
| // them in the web UI. | // them in the web UI. | ||||
| foreach ($headers as $header) { | foreach ($headers as $header) { | ||||
| list($header_key, $header_value) = $header; | list($header_key, $header_value) = $header; | ||||
| ▲ Show 20 Lines • Show All 270 Lines • ▼ Show 20 Lines | private function loadActors(array $actor_phids) { | ||||
| // Exclude the actor if their preferences are set. | // Exclude the actor if their preferences are set. | ||||
| $from_phid = $this->getParam('from'); | $from_phid = $this->getParam('from'); | ||||
| $from_actor = idx($actors, $from_phid); | $from_actor = idx($actors, $from_phid); | ||||
| if ($from_actor) { | if ($from_actor) { | ||||
| $from_user = id(new PhabricatorPeopleQuery()) | $from_user = id(new PhabricatorPeopleQuery()) | ||||
| ->setViewer($viewer) | ->setViewer($viewer) | ||||
| ->withPHIDs(array($from_phid)) | ->withPHIDs(array($from_phid)) | ||||
| ->needUserSettings(true) | |||||
| ->execute(); | ->execute(); | ||||
| $from_user = head($from_user); | $from_user = head($from_user); | ||||
| if ($from_user) { | if ($from_user) { | ||||
| $pref_key = PhabricatorUserPreferences::PREFERENCE_NO_SELF_MAIL; | $pref_key = PhabricatorEmailSelfActionsSetting::SETTINGKEY; | ||||
| $exclude_self = $from_user | $exclude_self = $from_user->getUserSetting($pref_key); | ||||
| ->loadPreferences() | |||||
| ->getPreference($pref_key); | |||||
| if ($exclude_self) { | if ($exclude_self) { | ||||
| $from_actor->setUndeliverable(PhabricatorMetaMTAActor::REASON_SELF); | $from_actor->setUndeliverable(PhabricatorMetaMTAActor::REASON_SELF); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| $all_prefs = id(new PhabricatorUserPreferencesQuery()) | $all_prefs = id(new PhabricatorUserPreferencesQuery()) | ||||
| ->setViewer(PhabricatorUser::getOmnipotentUser()) | ->setViewer(PhabricatorUser::getOmnipotentUser()) | ||||
| ->withUserPHIDs($actor_phids) | ->withUserPHIDs($actor_phids) | ||||
| ->execute(); | ->execute(); | ||||
| $all_prefs = mpull($all_prefs, null, 'getUserPHID'); | $all_prefs = mpull($all_prefs, null, 'getUserPHID'); | ||||
| $value_email = PhabricatorUserPreferences::MAILTAG_PREFERENCE_EMAIL; | $value_email = PhabricatorEmailTagsSetting::VALUE_EMAIL; | ||||
| // Exclude all recipients who have set preferences to not receive this type | // Exclude all recipients who have set preferences to not receive this type | ||||
| // of email (for example, a user who says they don't want emails about task | // of email (for example, a user who says they don't want emails about task | ||||
| // CC changes). | // CC changes). | ||||
| $tags = $this->getParam('mailtags'); | $tags = $this->getParam('mailtags'); | ||||
| if ($tags) { | if ($tags) { | ||||
| foreach ($all_prefs as $phid => $prefs) { | foreach ($all_prefs as $phid => $prefs) { | ||||
| $user_mailtags = $prefs->getPreference( | $user_mailtags = $prefs->getSettingValue( | ||||
| PhabricatorUserPreferences::PREFERENCE_MAILTAGS, | PhabricatorEmailTagsSetting::SETTINGKEY); | ||||
| array()); | |||||
| // The user must have elected to receive mail for at least one | // The user must have elected to receive mail for at least one | ||||
| // of the mailtags. | // of the mailtags. | ||||
| $send = false; | $send = false; | ||||
| foreach ($tags as $tag) { | foreach ($tags as $tag) { | ||||
| if (((int)idx($user_mailtags, $tag, $value_email)) == $value_email) { | if (((int)idx($user_mailtags, $tag, $value_email)) == $value_email) { | ||||
| $send = true; | $send = true; | ||||
| break; | break; | ||||
| Show All 36 Lines | if ($force_recipients) { | ||||
| PhabricatorMetaMTAActor::REASON_FORCE_HERALD); | PhabricatorMetaMTAActor::REASON_FORCE_HERALD); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| // Exclude recipients who don't want any mail. This rule is very strong | // Exclude recipients who don't want any mail. This rule is very strong | ||||
| // and runs last. | // and runs last. | ||||
| foreach ($all_prefs as $phid => $prefs) { | foreach ($all_prefs as $phid => $prefs) { | ||||
| $exclude = $prefs->getPreference( | $exclude = $prefs->getSettingValue( | ||||
| PhabricatorUserPreferences::PREFERENCE_NO_MAIL, | PhabricatorEmailNotificationsSetting::SETTINGKEY); | ||||
| false); | |||||
| if ($exclude) { | if ($exclude) { | ||||
| $actors[$phid]->setUndeliverable( | $actors[$phid]->setUndeliverable( | ||||
| PhabricatorMetaMTAActor::REASON_MAIL_DISABLED); | PhabricatorMetaMTAActor::REASON_MAIL_DISABLED); | ||||
| } | } | ||||
| } | } | ||||
| return $actors; | return $actors; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | if ($this->routingMap === null) { | ||||
| } | } | ||||
| $this->routingMap = $map; | $this->routingMap = $map; | ||||
| } | } | ||||
| return $this->routingMap; | return $this->routingMap; | ||||
| } | } | ||||
| /* -( Preferences )-------------------------------------------------------- */ | |||||
| private function loadPreferences($target_phid) { | |||||
| if (!self::shouldMultiplexAllMail()) { | |||||
| $target_phid = null; | |||||
| } | |||||
| if ($target_phid) { | |||||
| $preferences = id(new PhabricatorUserPreferencesQuery()) | |||||
| ->setViewer(PhabricatorUser::getOmnipotentUser()) | |||||
| ->withUserPHIDs(array($target_phid)) | |||||
| ->executeOne(); | |||||
| } else { | |||||
| $preferences = null; | |||||
| } | |||||
| // TODO: Here, we would load global preferences once they exist. | |||||
| if (!$preferences) { | |||||
| // If we haven't found suitable preferences yet, return an empty object | |||||
| // which implicitly has all the default values. | |||||
| $preferences = id(new PhabricatorUserPreferences()) | |||||
| ->attachUser(new PhabricatorUser()); | |||||
| } | |||||
| return $preferences; | |||||
| } | |||||
| private function shouldAddRePrefix(PhabricatorUserPreferences $preferences) { | |||||
| $default_value = PhabricatorEnv::getEnvConfig('metamta.re-prefix'); | |||||
| $value = $preferences->getPreference( | |||||
| PhabricatorEmailRePrefixSetting::SETTINGKEY); | |||||
| if ($value === null) { | |||||
| return $default_value; | |||||
| } | |||||
| return ($value == PhabricatorEmailRePrefixSetting::VALUE_RE_PREFIX); | |||||
| } | |||||
| private function shouldVarySubject(PhabricatorUserPreferences $preferences) { | |||||
| $default_value = PhabricatorEnv::getEnvConfig('metamta.vary-subjects'); | |||||
| $value = $preferences->getPreference( | |||||
| PhabricatorEmailVarySubjectsSetting::SETTINGKEY); | |||||
| if ($value === null) { | |||||
| return $default_value; | |||||
| } | |||||
| return ($value == PhabricatorEmailVarySubjectsSetting::VALUE_VARY_SUBJECTS); | |||||
| } | |||||
| private function shouldSendHTML(PhabricatorUserPreferences $preferences) { | |||||
| $value = $preferences->getSettingValue( | |||||
| PhabricatorEmailFormatSetting::SETTINGKEY); | |||||
| return ($value == PhabricatorEmailFormatSetting::VALUE_HTML_EMAIL); | |||||
| } | |||||
| /* -( PhabricatorPolicyInterface )----------------------------------------- */ | /* -( PhabricatorPolicyInterface )----------------------------------------- */ | ||||
| public function getCapabilities() { | public function getCapabilities() { | ||||
| return array( | return array( | ||||
| PhabricatorPolicyCapability::CAN_VIEW, | PhabricatorPolicyCapability::CAN_VIEW, | ||||
| ); | ); | ||||
| Show All 18 Lines | |||||