Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL][PHP]Zapisywanie podczepionych plików z maila
Forum PHP.pl > Forum > Przedszkole
phpamator
Hej wszystkim,

Pomocy, nawet "GiePeTto" sobie nie radzi.
Jakiś czas temu napisałem skrypt który sprawdza maile (raporty dmarc), jeśli raport zapisany jest w formacie gz, wszystko śmiga jak należy, zbiera mi raporty, zapisuje, przetwarza itd.
Gorzej, że ostatnio zacząłem dostawać raporty w zipach. Zmodyfikowałem kod, żeby wykrywał zip, gz i xml gdyby taki się pojawił.
Niestety nie chce mi nic poza gz zapisywać i nie widzę nigdzie dlaczego.
  1. <?php
  2.  
  3. function getSenderData($senderId)
  4. {
  5. $host = "localhost";
  6. $username = "moj_user";
  7. $password = "pasior";
  8. $dbname = "moja_baza";
  9.  
  10. try {
  11. $pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
  12. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  13. $pdo->exec("SET NAMES utf8");
  14.  
  15. $query = "SELECT `email_address`, `email_password` FROM `cxo_senders` WHERE `email_id` = :senderId AND `email_status` = 1 AND `email_type` = 1";
  16. $stmt = $pdo->prepare($query);
  17. $stmt->execute(['senderId' => $senderId]);
  18. $result = $stmt->fetch(PDO::FETCH_ASSOC);
  19.  
  20. return $result;
  21. } catch (PDOException $e) {
  22. die("Connection failed: " . $e->getMessage());
  23. }
  24. }
  25.  
  26. function isFileProcessed($pdo, $fileName)
  27. {
  28. $fileNameWithoutExtension = preg_replace('/\.(gz|xml|zip)$/', '', $fileName);
  29. $query = "SELECT COUNT(*) as count FROM `emails_data` WHERE `file_name` = :fileName";
  30. $stmt = $pdo->prepare($query);
  31. $stmt->execute(['fileName' => $fileNameWithoutExtension]);
  32. $result = $stmt->fetch(PDO::FETCH_ASSOC);
  33. return $result && $result['count'] > 0;
  34. }
  35.  
  36. $senderData = getSenderData(1);
  37. if (!$senderData) {
  38. die('Sender data not found.');
  39. }
  40.  
  41. $username = $senderData['email_address'];
  42. $password = $senderData['email_password'];
  43. $hostname = '{imap.gmail.com:993/imap/ssl}';
  44.  
  45. $inbox = imap_open($hostname . 'INBOX', $username, $password);
  46. if (!$inbox) {
  47. die('Cannot connect to the mailbox: ' . imap_last_error());
  48. }
  49.  
  50. // Sprawdzamy ostatnich 7 dni
  51. $date = date('d-M-Y', strtotime('-7 days'));
  52. $emails = imap_search($inbox, 'SINCE "' . $date . '"');
  53.  
  54. if (!$emails) {
  55. die('No emails.');
  56. }
  57.  
  58. $host = "localhost";
  59. $username = "moj_user";
  60. $password = "pasior";
  61. $dbname = "moja_baza";
  62.  
  63. try {
  64. $pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
  65. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  66. echo '<h1>' . count($emails) . '</h1>';
  67. foreach ($emails as $emailNumber) {
  68. $structure = imap_fetchstructure($inbox, $emailNumber);
  69. if (isset($structure->parts) && count($structure->parts)) {
  70. for ($i = 0; $i < count($structure->parts); $i++) {
  71. $part = $structure->parts[$i];
  72.  
  73. if ($part->ifdparameters) {
  74. foreach ($part->dparameters as $object) {
  75. if (strtolower($object->attribute) == 'filename') {
  76. $filename = $object->value;
  77. $fileExtension = pathinfo($filename, PATHINFO_EXTENSION);
  78. if (in_array($fileExtension, ['gz', 'xml', 'zip'])) {
  79. if (!isFileProcessed($pdo, $filename)) {
  80. $message = imap_fetchbody($inbox, $emailNumber, $i + 1);
  81.  
  82. if ($part->encoding == 3) {
  83. $message = base64_decode($message);
  84. } elseif ($part->encoding == 4) {
  85. $message = quoted_printable_decode($message);
  86. }
  87. echo 'Processed attachment: ' . $filename . "\n";
  88. $filePath = 'reports/' . $filename;
  89. file_put_contents($filePath, $message);
  90.  
  91. } else {
  92. echo 'Attachment already processed: ' . $filename . '<br>';
  93. }
  94. }
  95. }
  96. }
  97. }
  98. }
  99. }
  100. }
  101. imap_close($inbox);
  102.  
  103. echo "\nWszystkie nowe emails z attachmentami z ostatnich 7 dni zapisane.\n";
  104.  
  105. } catch (PDOException $e) {
  106. die("Connection failed: " . $e->getMessage());
  107. }
  108.  


Sprawdzam pliki czy już wcześniej były zapisane, żeby w bazie nie powielać wpisów
w kolejnym kroku analizuję raporty na potrzeby statystyki.
I wszystko działa super ale kurcze tylko z plikami gz .....

Nie słyszałem, żeby były jakieś ograniczenia w tej kwestii.

Pomóżcie.

Pozdrówka
nospor
Mowisz o tym kodzie

if (in_array($fileExtension, ['gz', 'xml', 'zip'])) {
if (!isFileProcessed($pdo, $filename)) {
$message = imap_fetchbody($inbox, $emailNumber, $i + 1);

if ($part->encoding == 3) {
$message = base64_decode($message);
} elseif ($part->encoding == 4) {
$message = quoted_printable_decode($message);
}
echo 'Processed attachment: ' . $filename . "\n";
$filePath = 'reports/' . $filename;
file_put_contents($filePath, $message);

} else {
echo 'Attachment already processed: ' . $filename . '<br>';
}
}

?
Jesli tak to masz tam dolownie kilka linijek. Zrob var_dumpa po kazdej z nich i patrz na ktorym etapie sie wychrzania
phpamator
Hej nospor,

Dzięki za podpowiedź, jak narazie ciągle to samo, próbuję wszystkiego. Wygląda, że nie tylko ja mam taki problem. niby z zipami nie jest to takie proste wink.gif
nospor
no ale porobiles te dumpy? Patrzyles ktora dokladnie linijka sie wyklada?
phpamator
Zaraz mnie trafi, widzę tylko nazwę attachmentu, jeśli gz mogę się dobrać do raw i zdekodować
ale za chiny nie mogę się dobrać do zip'a ...


Cytat(nospor @ 22.08.2024, 15:09:19 ) *
no ale porobiles te dumpy? Patrzyles ktora dokladnie linijka sie wyklada?

Tak, ale tam się nic nie wykłada, wszystko działa tylko nie widzi zawartości. Jak jest GZ to spoko ale jak zip to już ni chuchu, nazwę widzi ale kontentu niema.
Nie wiem jak to ugryźć
Tomplus
Wiesz jak wyglądają emaile? Mniej więcej tak...


Kod
Content-Type: multipart/mixed; boundary="------------TaUYvFy6EV2yQ1WgLj0dvZr0"
Message-ID: <fb28d9e4-0a61-4111-bcf4-ddf300b60d0e@domain>
Date: Thu, 4 Jul 2024 13:30:50 +0200
MIME-Version: 1.0
User-Agent: Mozilla Thunderbird
Content-Language: pl
To: client@domain
From: User <user@domain>
Subject: Topic

This is a multi-part message in MIME format.
--------------TaUYvFy6EV2yQ1WgLj0dvZr0
Content-Type: multipart/alternative;
boundary="------------mARFQCGuM1C7a8WawIf0UO9O"

--------------mARFQCGuM1C7a8WawIf0UO9O
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit

. .. . .. . . .. .CONTENT ., . .. . . ..

--------------mARFQCGuM1C7a8WawIf0UO9O
Content-Type: multipart/related;
boundary="------------ZeFqkVy4bqkDcUrfWPTj9O3B"

--------------ZeFqkVy4bqkDcUrfWPTj9O3B
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit

<!DOCTYPE html>
<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>. .. . .. . . .. .CONTENT ., . .. . . ..
    </p>
     </body>
</html>
--------------ZeFqkVy4bqkDcUrfWPTj9O3B
Content-Type: image/png; name="LHOungz0iNHOA3XX.png"
Content-Disposition: inline; filename="LHOungz0iNHOA3XX.png"
Content-Id: <part1.TbsmhwuG.6kv07t07@domain>
Content-Transfer-Encoding: base64

iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAFCklEQVR4AYWWA5AlWRqFv3Mz32uUq2a7
atq2baxt27aNwNi2bdu2bXumXD31MvOe3XjxoqIVsV9a5

--------------ZeFqkVy4bqkDcUrfWPTj9O3B--


--------------mARFQCGuM1C7a8WawIf0UO9O--
--------------TaUYvFy6EV2yQ1WgLj0dvZr0
Content-Type: text/plain; charset=UTF-8; name="file.conf"
Content-Disposition: attachment; filename="file.conf"
Content-Transfer-Encoding: base64

W0ludGVyZmFjZV0KUHJpdmF0ZUtleSA9IHlKSFhDZ1BCdko3Nkc1MWh3RERSbUhRQTJWeE56

--------------TaUYvFy6EV2yQ1WgLj0dvZr0--



Po dumpie powinieneś mieć właśnie taką treść, następnie metoda `parts` powinna dać ci właśnie takie dodatkowe części emaile zawierające zakodowane załączniki.
phpamator
Hej Tomplus,

No tak, wszystko pięknie tyle, że w parts niema jakoś encoded zip.
wyciągam tylko jeśli plik załączony jest w formacie gz, a jeśli jest w zip to mi go poprostu nie znajduje. Tytuł pliku owszem ale zawartości już ni chu chu

dlatego mnie to tak drażni.

Masz jakiś działający przykład dla podglądu ?
Tomplus
Ok, spróbuj wyświetlić surowego emaila. Zobaczysz jak skonstruowana jest część dla zip.
Salvation
Ja po tym kodzie nie widzę, żebyś robił cokolwiek z załącznikiem:
  1. if (strtolower($object->attribute) == 'filename') {
  2. $filename = $object->value;
  3. $fileExtension = pathinfo($filename, PATHINFO_EXTENSION);
  4. if (in_array($fileExtension, ['gz', 'xml', 'zip'])) {
  5. if (!isFileProcessed($pdo, $filename)) {
  6. $message = imap_fetchbody($inbox, $emailNumber, $i + 1);
  7.  
  8. if ($part->encoding == 3) {
  9. $message = base64_decode($message);
  10. } elseif ($part->encoding == 4) {
  11. $message = quoted_printable_decode($message);
  12. }
  13. echo 'Processed attachment: ' . $filename . "\n";
  14. $filePath = 'reports/' . $filename;
  15. file_put_contents($filePath, $message);
  16.  
  17. } else {
  18. echo 'Attachment already processed: ' . $filename . '<br>';
  19. }
  20. }
  21. }

Tutaj sprawdzasz czy masz już taki załącznik w bazie:
  1. if (!isFileProcessed($pdo, $filename))

ale jak już masz, to go nie nadpisujesz, a później jedynie co robisz, to pobierasz "body" z maila:
  1. $message = imap_fetchbody($inbox, $emailNumber, $i + 1);

I je obrabiasz w zależności od kodowania.

Pomijam fakt, ze nie widzę INSERT-a do bazy z informacją o pliku, ale... Gdzie finalnie jest załącznik z maila? W zmiennej $message?
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.