30191edae62b4122337e3e29cdcd4e2d527d53fa
[friendica.git/.git] / src / Model / Mail.php
1 <?php
2
3 /**
4  * @file src/Model/Mail.php
5  */
6 namespace Friendica\Model;
7
8 use Friendica\Core\L10n;
9 use Friendica\Core\Logger;
10 use Friendica\Core\System;
11 use Friendica\Core\Worker;
12 use Friendica\Model\Item;
13 use Friendica\Database\DBA;
14 use Friendica\Network\Probe;
15 use Friendica\Util\DateTimeFormat;
16 use Friendica\Worker\Delivery;
17
18 /**
19  * Class to handle private messages
20  */
21 class Mail
22 {
23         /**
24          * Insert received private message
25          *
26          * @param array $msg
27          * @return int|boolean Message ID or false on error
28          */
29         public static function insert($msg)
30         {
31                 $user = User::getById($msg['uid']);
32
33                 if (!isset($msg['reply'])) {
34                         $msg['reply'] = DBA::exists('mail', ['parent-uri' => $msg['parent-uri']]);
35                 }
36
37                 if (empty($msg['convid'])) {
38                         $mail = DBA::selectFirst('mail', ['convid'], ["`convid` != 0 AND `parent-uri` = ?", $msg['parent-uri']]);
39                         if (DBA::isResult($mail)) {
40                                 $msg['convid'] = $mail['convid'];
41                         }
42                 }
43
44                 if (empty($msg['guid'])) {
45                         $host = parse_url($msg['from-url'], PHP_URL_HOST);
46                         $msg['guid'] = Item::guidFromUri($msg['uri'], $host);
47                 }
48
49                 DBA::lock('mail');
50
51                 if (DBA::exists('mail', ['uri' => $msg['uri'], 'uid' => $msg['uid']])) {
52                         DBA::unlock();
53                         Logger::info('duplicate message already delivered.');
54                         return false;
55                 }
56
57                 DBA::insert('mail', $msg);
58
59                 $msg['id'] = DBA::lastInsertId();
60
61                 DBA::unlock();
62
63                 if (!empty($msg['convid'])) {
64                         DBA::update('conv', ['updated' => DateTimeFormat::utcNow()], ['id' => $msg['convid']]);
65                 }
66
67                 // send notifications.
68                 $notif_params = [
69                         'type' => NOTIFY_MAIL,
70                         'notify_flags' => $user['notify-flags'],
71                         'language' => $user['language'],
72                         'to_name' => $user['username'],
73                         'to_email' => $user['email'],
74                         'uid' => $user['uid'],
75                         'item' => $msg,
76                         'parent' => 0,
77                         'source_name' => $msg['from-name'],
78                         'source_link' => $msg['from-url'],
79                         'source_photo' => $msg['from-photo'],
80                         'verb' => ACTIVITY_POST,
81                         'otype' => 'mail'
82                 ];
83
84                 notification($notif_params);
85
86                 Logger::info('Mail is processed, notification was sent.', ['id' => $msg['id'], 'uri' => $msg['uri']]);
87
88                 return $msg['id'];
89         }
90
91         /**
92          * Send private message
93          *
94          * @param integer $recipient recipient id, default 0
95          * @param string  $body      message body, default empty
96          * @param string  $subject   message subject, default empty
97          * @param string  $replyto   reply to
98          * @return int
99          * @throws \Friendica\Network\HTTPException\InternalServerErrorException
100          */
101         public static function send($recipient = 0, $body = '', $subject = '', $replyto = '')
102         {
103                 $a = \get_app();
104
105                 if (!$recipient) {
106                         return -1;
107                 }
108
109                 if (!strlen($subject)) {
110                         $subject = L10n::t('[no subject]');
111                 }
112
113                 $me = DBA::selectFirst('contact', [], ['uid' => local_user(), 'self' => true]);
114                 $contact = DBA::selectFirst('contact', [], ['id' => $recipient, 'uid' => local_user()]);
115
116                 if (!(count($me) && (count($contact)))) {
117                         return -2;
118                 }
119
120                 $guid = System::createUUID();
121                 $uri = Item::newURI(local_user(), $guid);
122
123                 $convid = 0;
124                 $reply = false;
125
126                 // look for any existing conversation structure
127
128                 if (strlen($replyto)) {
129                         $reply = true;
130                         $condition = ["`uid` = ? AND (`uri` = ? OR `parent-uri` = ?)",
131                                 local_user(), $replyto, $replyto];
132                         $mail = DBA::selectFirst('mail', ['convid'], $condition);
133                         if (DBA::isResult($mail)) {
134                                 $convid = $mail['convid'];
135                         }
136                 }
137
138                 $convuri = '';
139                 if (!$convid) {
140                         // create a new conversation
141                         $recip_host = substr($contact['url'], strpos($contact['url'], '://') + 3);
142                         $recip_host = substr($recip_host, 0, strpos($recip_host, '/'));
143
144                         $recip_handle = (($contact['addr']) ? $contact['addr'] : $contact['nick'] . '@' . $recip_host);
145                         $sender_handle = $a->user['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3);
146
147                         $conv_guid = System::createUUID();
148                         $convuri = $recip_handle . ':' . $conv_guid;
149
150                         $handles = $recip_handle . ';' . $sender_handle;
151
152                         $fields = ['uid' => local_user(), 'guid' => $conv_guid, 'creator' => $sender_handle,
153                                 'created' => DateTimeFormat::utcNow(), 'updated' => DateTimeFormat::utcNow(),
154                                 'subject' => $subject, 'recips' => $handles];
155                         if (DBA::insert('conv', $fields)) {
156                                 $convid = DBA::lastInsertId();
157                         }
158                 }
159
160                 if (!$convid) {
161                         Logger::log('send message: conversation not found.');
162                         return -4;
163                 }
164
165                 if (!strlen($replyto)) {
166                         $replyto = $convuri;
167                 }
168
169                 $post_id = null;
170                 $success = DBA::insert(
171                         'mail',
172                         [
173                                 'uid' => local_user(),
174                                 'guid' => $guid,
175                                 'convid' => $convid,
176                                 'from-name' => $me['name'],
177                                 'from-photo' => $me['thumb'],
178                                 'from-url' => $me['url'],
179                                 'contact-id' => $recipient,
180                                 'title' => $subject,
181                                 'body' => $body,
182                                 'seen' => 1,
183                                 'reply' => $reply,
184                                 'replied' => 0,
185                                 'uri' => $uri,
186                                 'parent-uri' => $replyto,
187                                 'created' => DateTimeFormat::utcNow()
188                         ]
189                 );
190
191                 if ($success) {
192                         $post_id = DBA::lastInsertId();
193                 }
194
195                 /**
196                  *
197                  * When a photo was uploaded into the message using the (profile wall) ajax
198                  * uploader, The permissions are initially set to disallow anybody but the
199                  * owner from seeing it. This is because the permissions may not yet have been
200                  * set for the post. If it's private, the photo permissions should be set
201                  * appropriately. But we didn't know the final permissions on the post until
202                  * now. So now we'll look for links of uploaded messages that are in the
203                  * post and set them to the same permissions as the post itself.
204                  *
205                  */
206                 $match = null;
207                 if (preg_match_all("/\[img\](.*?)\[\/img\]/", $body, $match)) {
208                         $images = $match[1];
209                         if (count($images)) {
210                                 foreach ($images as $image) {
211                                         if (!stristr($image, System::baseUrl() . '/photo/')) {
212                                                 continue;
213                                         }
214                                         $image_uri = substr($image, strrpos($image, '/') + 1);
215                                         $image_uri = substr($image_uri, 0, strpos($image_uri, '-'));
216                                         Photo::update(['allow-cid' => '<' . $recipient . '>'], ['resource-id' => $image_uri, 'album' => 'Wall Photos', 'uid' => local_user()]);
217                                 }
218                         }
219                 }
220
221                 if ($post_id) {
222                         Worker::add(PRIORITY_HIGH, "Notifier", Delivery::MAIL, $post_id);
223                         return intval($post_id);
224                 } else {
225                         return -3;
226                 }
227         }
228
229         /**
230          * @param array  $recipient recipient, default empty
231          * @param string $body      message body, default empty
232          * @param string $subject   message subject, default empty
233          * @param string $replyto   reply to, default empty
234          * @return int
235          * @throws \Friendica\Network\HTTPException\InternalServerErrorException
236          * @throws \ImagickException
237          */
238         public static function sendWall(array $recipient = [], $body = '', $subject = '', $replyto = '')
239         {
240                 if (!$recipient) {
241                         return -1;
242                 }
243
244                 if (!strlen($subject)) {
245                         $subject = L10n::t('[no subject]');
246                 }
247
248                 $guid = System::createUUID();
249                 $uri = Item::newURI(local_user(), $guid);
250
251                 $me = Probe::uri($replyto);
252
253                 if (!$me['name']) {
254                         return -2;
255                 }
256
257                 $conv_guid = System::createUUID();
258
259                 $recip_handle = $recipient['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3);
260
261                 $sender_nick = basename($replyto);
262                 $sender_host = substr($replyto, strpos($replyto, '://') + 3);
263                 $sender_host = substr($sender_host, 0, strpos($sender_host, '/'));
264                 $sender_handle = $sender_nick . '@' . $sender_host;
265
266                 $handles = $recip_handle . ';' . $sender_handle;
267
268                 $convid = null;
269                 $fields = ['uid' => $recipient['uid'], 'guid' => $conv_guid, 'creator' => $sender_handle,
270                         'created' => DateTimeFormat::utcNow(), 'updated' => DateTimeFormat::utcNow(),
271                         'subject' => $subject, 'recips' => $handles];
272                 if (DBA::insert('conv', $fields)) {
273                         $convid = DBA::lastInsertId();
274                 }
275
276                 if (!$convid) {
277                         Logger::log('send message: conversation not found.');
278                         return -4;
279                 }
280
281                 DBA::insert(
282                         'mail',
283                         [
284                                 'uid' => $recipient['uid'],
285                                 'guid' => $guid,
286                                 'convid' => $convid,
287                                 'from-name' => $me['name'],
288                                 'from-photo' => $me['photo'],
289                                 'from-url' => $me['url'],
290                                 'contact-id' => 0,
291                                 'title' => $subject,
292                                 'body' => $body,
293                                 'seen' => 0,
294                                 'reply' => 0,
295                                 'replied' => 0,
296                                 'uri' => $uri,
297                                 'parent-uri' => $replyto,
298                                 'created' => DateTimeFormat::utcNow(),
299                                 'unknown' => 1
300                         ]
301                 );
302
303                 return 0;
304         }
305 }