3 abstract class PhabricatorMailAdapter
9 private $options = array();
11 private $supportsInbound = true;
12 private $supportsOutbound = true;
15 final public function getAdapterType() {
16 return $this->getPhobjectClassConstant('ADAPTERTYPE');
19 final public static function getAllAdapters() {
20 return id(new PhutilClassMapQuery())
21 ->setAncestorClass(__CLASS__
)
22 ->setUniqueMethod('getAdapterType')
26 abstract public function getSupportedMessageTypes();
27 abstract public function sendMessage(PhabricatorMailExternalMessage
$message);
30 * Return true if this adapter supports setting a "Message-ID" when sending
33 * This is an ugly implementation detail because mail threading is a horrible
34 * mess, implemented differently by every client in existence.
36 public function supportsMessageIDHeader() {
40 final public function supportsMessageType($message_type) {
41 if ($this->mediaMap
=== null) {
42 $media_map = $this->getSupportedMessageTypes();
43 $media_map = array_fuse($media_map);
46 $config_map = $this->media
;
47 $config_map = array_fuse($config_map);
49 $media_map = array_intersect_key($media_map, $config_map);
52 $this->mediaMap
= $media_map;
55 return isset($this->mediaMap
[$message_type]);
58 final public function setMedia(array $media) {
59 $native_map = $this->getSupportedMessageTypes();
60 $native_map = array_fuse($native_map);
62 foreach ($media as $medium) {
63 if (!isset($native_map[$medium])) {
66 'Adapter ("%s") is configured for medium "%s", but this is not '.
67 'a supported delivery medium. Supported media are: %s.',
70 implode(', ', $native_map)));
74 $this->media
= $media;
75 $this->mediaMap
= null;
79 final public function getMedia() {
83 final public function setKey($key) {
88 final public function getKey() {
92 final public function setPriority($priority) {
93 $this->priority
= $priority;
97 final public function getPriority() {
98 return $this->priority
;
101 final public function setSupportsInbound($supports_inbound) {
102 $this->supportsInbound
= $supports_inbound;
106 final public function getSupportsInbound() {
107 return $this->supportsInbound
;
110 final public function setSupportsOutbound($supports_outbound) {
111 $this->supportsOutbound
= $supports_outbound;
115 final public function getSupportsOutbound() {
116 return $this->supportsOutbound
;
119 final public function getOption($key) {
120 if (!array_key_exists($key, $this->options
)) {
123 'Mailer ("%s") is attempting to access unknown option ("%s").',
128 return $this->options
[$key];
131 final public function setOptions(array $options) {
132 $this->validateOptions($options);
133 $this->options
= $options;
137 abstract protected function validateOptions(array $options);
139 abstract public function newDefaultOptions();
141 final protected function guessIfHostSupportsMessageID($config, $host) {
142 // See T13265. Mailers like "SMTP" and "sendmail" usually allow us to
143 // set the "Message-ID" header to a value we choose, but we may not be
144 // able to if the mailer is being used as API glue and the outbound
145 // pathway ends up routing to a service with an SMTP API that selects
146 // its own "Message-ID" header, like Amazon SES.
148 // If users configured a behavior explicitly, use that behavior.
149 if ($config !== null) {
153 // If the server we're connecting to is part of a service that we know
154 // does not support "Message-ID", guess that we don't support "Message-ID".
155 if ($host !== null) {
156 $host_blocklist = array(
157 '/\.amazonaws\.com\z/',
158 '/\.postmarkapp\.com\z/',
159 '/\.sendgrid\.net\z/',
162 $host = phutil_utf8_strtolower($host);
163 foreach ($host_blocklist as $regexp) {
164 if (preg_match($regexp, $host)) {