1
0

sms.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. <?php
  2. require_once 'sms.secrets';
  3. define('DEBUG', true);
  4. define('PARAMS', array('to', 'from', 'body', 'is_mms'));
  5. define('PARAMS_MMS', array('url', 'file_name', 'mime_type', 'file_size'));
  6. define('DEFAULT_NUM', '8002221222');
  7. define('MAX_ATTACHMENT_SIZE', 25*(1024*1024));
  8. $file = null;
  9. if (DEBUG) {
  10. $file = @tempnam('/var/tmp', 'sms.');
  11. if (!$file) {
  12. fail('STORE_INIT');
  13. }
  14. debug_log('File: ' . $file);
  15. }
  16. debug_log('INIT');
  17. use PHPMailer\PHPMailer\PHPMailer;
  18. use PHPMailer\PHPMailer\Exception;
  19. require_once 'PHPMailer/src/Exception.php';
  20. require_once 'PHPMailer/src/PHPMailer.php';
  21. require_once 'PHPMailer/src/SMTP.php';
  22. debug_log('READ');
  23. $raw = @file_get_contents('php://input');
  24. if (!$raw) {
  25. fail('READ');
  26. }
  27. if (DEBUG) {
  28. if (!@file_put_contents($file . '.raw', print_r($raw, true))) {
  29. fail('STORE_RAW');
  30. }
  31. }
  32. debug_log('JSON');
  33. $data = json_decode($raw);
  34. if (!$data || !is_object($data)) {
  35. fail('JSON');
  36. }
  37. unset($raw);
  38. if (DEBUG) {
  39. if (!@file_put_contents($file . '.decoded', print_r($data, true))) {
  40. fail('STORE_DECODED');
  41. }
  42. }
  43. debug_log('FIND');
  44. if (!property_exists($data, 'data') || !is_object($data->{'data'}) ||
  45. !property_exists($data->{'data'}, 'attributes') ||
  46. !is_object($data->{'data'}->{'attributes'})
  47. ) {
  48. fail('FIND');
  49. }
  50. $msg = $data->{'data'}->{'attributes'};
  51. debug_log('PARSE');
  52. foreach (PARAMS as $param) {
  53. if (!property_exists($msg, $param)) {
  54. fail('PARSE: ' . $param);
  55. }
  56. }
  57. $sms = array();
  58. foreach (PARAMS as $param) {
  59. $sms[$param] = $msg->{$param};
  60. }
  61. unset($msg);
  62. cleanNum($sms, 'to');
  63. cleanNum($sms, 'from');
  64. if (!$sms['body']) {
  65. $sms['body'] = ' ';
  66. }
  67. debug_log('FIND_MMS');
  68. if ($sms['is_mms']) {
  69. if (!property_exists($data, 'included') || !is_array($data->{'included'})) {
  70. fail('FIND_MMS');
  71. }
  72. $msg = $data->{'included'};
  73. foreach ($msg as $part) {
  74. if (!property_exists($part, 'attributes') || !is_object($part->{'attributes'})) {
  75. fail('FIND_MMS_PART');
  76. }
  77. $part = $part->{'attributes'};
  78. debug_log('PARSE_MMS');
  79. foreach (PARAMS_MMS as $param) {
  80. if (!property_exists($part, $param)) {
  81. fail('PARSE_MMS: ' . $param);
  82. }
  83. }
  84. $media = array();
  85. foreach (PARAMS_MMS as $param) {
  86. $media[$param] = $part->{$param};
  87. }
  88. $sms['media'][] = $media;
  89. unset($msg);
  90. }
  91. }
  92. unset($data);
  93. if (DEBUG) {
  94. debug_log(print_r($sms, true));
  95. if (!@file_put_contents($file, print_r($sms, true))) {
  96. fail('STORE_PARSED');
  97. }
  98. }
  99. debug_log('MAIL');
  100. $mail = new PHPMailer();
  101. $mail->setFrom($sms['from'] . '@' . FROM_DOMAIN, 'SMS ' . $sms['from_pretty']);
  102. $mail->addAddress(TO_ADDR, TO_NAME);
  103. $mail->Subject = 'SMS Message ' . $sms['from_pretty'] . ' => ' . $sms['to_pretty'];
  104. $mail->Body = $sms['body'];
  105. $files = array();
  106. foreach ($sms['media'] as $file) {
  107. debug_log('MEDIA');
  108. if ($file['file_size'] < 1 || $file['file_size'] > MAX_ATTACHMENT_SIZE) {
  109. debug_log('FILE SIZE: ' . $file['file_size']);
  110. $mail->Body .= "\nWill not fetch " .
  111. '(' . $file['file_size'] . '/' . MAX_ATTACHMENT_SIZE . '): ' .
  112. $file['url'] . "\n";
  113. continue;
  114. }
  115. $path = download($file['url']);
  116. if (!$path) {
  117. debug_log('DOWNLOAD FAILED: ' . $file['url']);
  118. $mail->Body .= "\nCould not fetch: " . $file['url'] . "\n";
  119. continue;
  120. }
  121. debug_log('ADDING: ' . $path);
  122. $files[] = $path;
  123. $mail->addAttachment($path, $file['file_name'], 'base64', $file['mime_type'], 'attachment');
  124. }
  125. if (!$mail->send()) {
  126. debug_log('Mail error: ' . $mail->ErrorInfo);
  127. fail('MAIL');
  128. }
  129. foreach ($files as $path) {
  130. debug_log('REMOVING: ' . $path);
  131. @unlink($path);
  132. }
  133. unset($mail);
  134. debug_log('CLEANUP');
  135. unset($sms);
  136. function cleanNum(&$sms, $field) {
  137. if (preg_match('/\d*(\d{3})(\d{3})(\d{4})\D*$/', $sms[$field], $matches)) {
  138. $sms[$field] = $matches[1] . $matches[2] . $matches[3];
  139. $sms[$field . '_pretty'] = '(' . $matches[1] . ') ' . $matches[2] . '-' . $matches[3];
  140. } else {
  141. debug_log($field . ' number format error: ' . $sms[$field]);
  142. $sms[$field] = DEFAULT_NUM;
  143. }
  144. }
  145. function download($url) {
  146. $file = @tempnam(sys_get_temp_dir(), 'SMS_media.');
  147. if (!$file) {
  148. return false;
  149. }
  150. $fp = @fopen($file, 'w+');
  151. if (!$fp) {
  152. return false;
  153. }
  154. $ch = curl_init($url);
  155. curl_setopt($ch, CURLOPT_FILE, $fp);
  156. curl_setopt($ch, CURLOPT_SSLVERSION, 'CURL_SSLVERSION_MAX_DEFAULT');
  157. curl_exec($ch);
  158. $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  159. curl_close($ch);
  160. fclose($fp);
  161. if ($code == 200) {
  162. return $file;
  163. } else {
  164. unlink($file);
  165. return false;
  166. }
  167. }
  168. function fail($msg = 'Unknown error', $code = 500) {
  169. http_response_code($code);
  170. echo 'Unable to process request: ' . $msg . "\n";
  171. exit(0);
  172. }
  173. function debug_log($msg) {
  174. if (! DEBUG) {
  175. return;
  176. }
  177. echo $msg . "\n";
  178. }
  179. ?>