dontknowphp Posted December 1, 2022 Share Posted December 1, 2022 Hi, I was wondering if there is any simple library that could read/fetch emails from an smtp email account that I could use to save the details on my database. Use Case: Execute a cron job every X minutes to check if any new emails have arrived in the inbox and save them to the database (just like most of the support ticketing systems work) Looking to create a simple support ticketing system. Quote Link to comment https://forums.phpfreaks.com/topic/315603-fetch-emails-smtp-save-details-to-db/ Share on other sites More sharing options...
kicken Posted December 1, 2022 Share Posted December 1, 2022 SMTP is sending emails to servers. Reading sent emails as a client is done with either IMAP or POP. PHP has an extension for that. Quote Link to comment https://forums.phpfreaks.com/topic/315603-fetch-emails-smtp-save-details-to-db/#findComment-1603117 Share on other sites More sharing options...
dontknowphp Posted December 1, 2022 Author Share Posted December 1, 2022 thanks for the info, is it possible to connect to a mailbox with imap so the emails won't get deleted like they do with pop3? Quote Link to comment https://forums.phpfreaks.com/topic/315603-fetch-emails-smtp-save-details-to-db/#findComment-1603118 Share on other sites More sharing options...
kicken Posted December 1, 2022 Share Posted December 1, 2022 Yes, imap leaves the messages on the server until you explicitly delete them. Quote Link to comment https://forums.phpfreaks.com/topic/315603-fetch-emails-smtp-save-details-to-db/#findComment-1603120 Share on other sites More sharing options...
dontknowphp Posted December 1, 2022 Author Share Posted December 1, 2022 can you share an example of an imap connection? i've tried a few example ive found online but i cant make it to work. <?php $db->query("SELECT * FROM st_settings"); while($db->movenext()) { $st_settings[$db->col["name"]] = $db->col["value"]; } $inbox = imap_open("{".$st_settings["SMTP_HOST"].":".$st_settings["SMTP_PORT"]."/pop3/novalidate-cert}", $st_settings["SMTP_USERNAME"], $st_settings["SMTP_PASSWORD"]); $num = imap_num_msg($inbox); echo $num; // close the connection imap_expunge($inbox); imap_close($inbox); ?> Quote Link to comment https://forums.phpfreaks.com/topic/315603-fetch-emails-smtp-save-details-to-db/#findComment-1603123 Share on other sites More sharing options...
kicken Posted December 1, 2022 Share Posted December 1, 2022 (edited) Sure. First, as mentioned before this is not SMTP, so all the SMTP_* constants you are using are either the wrong values or incorrectly named. Either make new IMAP settings to use or rename your constants. Second, this is based on some code I have that checks an email account for a one-time-password code so I can login and download data from a site. <?php //Example parameters. $host = '{imap.example.com:993/ssl/readonly}'; $mailbox = 'otp@example.com'; $password = ''; function getSecurityCode(string $host, string $mailbox, string $password) : ?string{ $authCode = null; $startTime = time(); do { sleep(5); $handle = imap_open($host, $mailbox, $password, OP_READONLY, 5); if (!$handle){ throw new RuntimeException('Unable to open mailbox'); } $messageList = imap_sort($handle, SORTDATE, 1); foreach ($messageList as $messageNumber){ $messageInfo = imap_fetch_overview($handle, $messageNumber)[0]; if (isOTPEmail($messageInfo) && isReceivedInLast5Minutes($messageInfo)){ $authCode = extractAuthCode(imap_body($handle, $messageNumber)); break; } } imap_close($handle); } while (!$authCode && time() - $startTime < 300); return $authCode; } function isOTPEmail(stdClass $messageInfo) : bool{ if (!isset($messageInfo->subject)){ return false; } return stripos($messageInfo->from, 'donotreply@example.com') !== false && stripos($messageInfo->subject, 'One-Time Passcode') !== false; } function isReceivedInLast5Minutes(stdClass $messageInfo) : bool{ if (!isset($messageInfo->date)){ return false; } $date = DateTime::createFromFormat(DateTimeInterface::RFC2822, $messageInfo->date); if ($date === false){ $date = DateTime::createFromFormat(DateTimeInterface::RFC2822 . ' (\G\M\T)', $messageInfo->date); } if ($date === false){ return false; } $now = new DateTime('', $date->getTimezone()); $now->sub(new DateInterval('PT5M')); return $date > $now; } Edited December 1, 2022 by kicken 1 Quote Link to comment https://forums.phpfreaks.com/topic/315603-fetch-emails-smtp-save-details-to-db/#findComment-1603127 Share on other sites More sharing options...
dontknowphp Posted December 2, 2022 Author Share Posted December 2, 2022 thank you for the example, ive managed to make it work. However, since i want to save attachments as well, isn't there any "known" library that has all these functions so i don't lose time to develop all these functionality? some sort of "Plug and play" library? Quote Link to comment https://forums.phpfreaks.com/topic/315603-fetch-emails-smtp-save-details-to-db/#findComment-1603173 Share on other sites More sharing options...
gizmola Posted December 2, 2022 Share Posted December 2, 2022 I'm sure there are many such libraries but this one has been used by many people: https://github.com/ddeboer/imap This one comes up as the most used in packagist: https://github.com/barbushin/php-imap Quote Link to comment https://forums.phpfreaks.com/topic/315603-fetch-emails-smtp-save-details-to-db/#findComment-1603191 Share on other sites More sharing options...
dontknowphp Posted December 7, 2022 Author Share Posted December 7, 2022 Hello @gizmola @kicken Thank you for your help, i ended up using the library from barbushin. However, i have one more question. How can I "detect" which reply is associated with the original email? Steps 1) User sends email to example@example.com 2) cron job runs checks for new emails and creates new "tickets" (save to db) 3) Admin replies from the webapp 4) User replies to the admin's response 5) cron job runs detects new email -> i need somehow to map it with the existing ticket so the system won't create a new ticket again. I suspect that the "messageid" has something to do with this but i haven't found any way to take advantage of it. Quote Link to comment https://forums.phpfreaks.com/topic/315603-fetch-emails-smtp-save-details-to-db/#findComment-1603314 Share on other sites More sharing options...
kicken Posted December 7, 2022 Share Posted December 7, 2022 In my experience, such systems usually just have some identifier in the email, usually the subject which is used to associate the email with the internal ticket system. If you want to try and do it without such an identifier, look at the In-Reply-To and/or References headers which should contain the original email message id. Quote Link to comment https://forums.phpfreaks.com/topic/315603-fetch-emails-smtp-save-details-to-db/#findComment-1603341 Share on other sites More sharing options...
dontknowphp Posted December 8, 2022 Author Share Posted December 8, 2022 17 hours ago, kicken said: In my experience, such systems usually just have some identifier in the email, usually the subject which is used to associate the email with the internal ticket system. The subject may change in the ticketing, so mapping it with the subject may not be reliable 17 hours ago, kicken said: If you want to try and do it without such an identifier, look at the In-Reply-To and/or References headers which should contain the original email message id. I am confused with this bit, when i am replying through the ticket system do i need to construct the "message id" or is that automatically done? Quote Link to comment https://forums.phpfreaks.com/topic/315603-fetch-emails-smtp-save-details-to-db/#findComment-1603359 Share on other sites More sharing options...
kicken Posted December 8, 2022 Share Posted December 8, 2022 2 hours ago, dontknowphp said: The subject may change in the ticketing, so mapping it with the subject may not be reliable You wouldn't match the whole subject, just some identifier. For example the subject may be: [Ticket #1234] Help with something. Then you'd just extract the 1234 and lookup that ticket. Even if someone changes the subject, so long as that prefix is left in it will be fine. In my experience, people do not typically change a subject when replying so it should be fairly reliable. If for some reason you cannot automatically match it to a ticket, you could put the message into some queue for a person to manually assign to a ticket. 3 hours ago, dontknowphp said: I am confused with this bit, when i am replying through the ticket system do i need to construct the "message id" or is that automatically done? If you're generating the email then you'll probably need to generate the Message-Id header as well. If you're using a library to create and send emails it might do that automatically. Quote Link to comment https://forums.phpfreaks.com/topic/315603-fetch-emails-smtp-save-details-to-db/#findComment-1603363 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.