I'm working on Symfony 2.7. I have to create a mail client to retrieve and send mails from the mail server (IMAP protocol); to do this, I used the php-imap classes, with a bundle (included with composer). But I'm not sure about the way I should use them : Do I extend the classes to represent my Mail and Mailbox objects, or should I create new classes from scratch ?
I don't want to manipulate IMAP straight from my controllers, I think it would be too long to process. Is that right?
Is it a good idea to create a "watcher" (periodic command executed by cron) to parse new mails every 2 minutes or so, create new mails entity from them, and send the waiting ones? Could I do that while extending the php-imap classes? This way I would use one class only? But wouldn't that be too heavy to store for the database ?
What's the correct way to fetch only new mails ? Do I have to use a specific function, like imap_check, or do I do that by a search criteria (like date from the last check) ? I tried with criteria "NEW", but that was unsuccessful.
Also, the mailboxes I have to parse are quite heavy. I tried to make a search in one of them with "ALL" criteria, but it's really long to process ! Am I doing it right ? Do I just have to be patient ?
Here's what I did for the "watcher" function :
use PhpImap\Mailbox as ImapMailbox;
class GetNewMailsCommand extends ContainerAwareCommand
{
$em = $this->getContainer()->get('doctrine')->getEntityManager();
$mailboxes = $em->getRepository('MIPMailBundle:MailBox')->findAllActive();
foreach ($mailboxes as $mailbox){
$imapBox = new ImapMailbox('{'.$mailbox->getServer().':143/notls/norsh/novalidate-cert}INBOX', $mailbox->getAdress(), $mailbox->getPassword());
if ($mailbox->getMails() == null || empty($mailbox->getMails())){
$mailsIds = $imapBox->searchMailbox('ALL');
if(!$mailsIds) {
$output->writeln($mailbox->getAdress() . " is empty");
}
} else {
$mailsIds = $imapBox->searchMailbox('NEW');
if(!$mailsIds) {
$output->writeln("No new mail for " . $mailbox->getAdress());
}
}
foreach ($mailsIds as $mailId){
$imapMail = $imapBox->getMail($mailId);
$mail = new Mail($mailbox, false);
$mail->setSubject($imapMail->subject);
$mail->setSender($imapMail->fromAddress);
$mail->setCc($imapMail->cc);
$mail->setBcc($imapMail->bcc);
$mail->setToString($imapMail->toString);
$mail->setContent($imapMail->textPlain);
$mail->setDate(new \DateTime($imapMail->date));
foreach ($imapMail->to as $toAddress){
$mail->addRecipient($toAddress);
}
$em->persist($mail);
}
}
$em->flush();
And here's my entities :
class MailBox
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var
*
* @ORM\OneToOne(targetEntity="\MIP\CRMBundle\Entity\Agency", inversedBy="mailBox", cascade={"persist"})
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true)
*/
private $user;
/**
* @var Agency
*
* @ORM\ManyToMany(targetEntity="\MIP\CRMBundle\Entity\Agency", inversedBy="mailBoxShared")
* @ORM\JoinTable(name="mailbox_shared")
*/
private $sharedTo;
/**
* @var
*
* @ORM\OneToMany(targetEntity="Mail", mappedBy="mailBox")
*/
private $mails;
/**
* @var boolean
*
* @ORM\Column(name="active", type="boolean")
*/
private $active;
/**
* @var string
*
* @ORM\Column(name="adress", type="string", length=255)
*/
private $adress;
/**
* @var string
*
* @ORM\Column(name="server", type="string", length=255)
*/
private $server;
/**
* @var string
*
* @ORM\Column(name="password", type="string", length=255)
*/
private $password;
/**
* @var integer
*
* @ORM\Column(name="port", type="integer")
*/
private $port;
/**
* MailBox constructor.
*/
public function __construct()
{
$this->sharedTo = new ArrayCollection();
$this->mails = new ArrayCollection();
}
class Mail
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="sender", type="string", length=255)
*/
private $sender;
/**
* @var array
*
* @ORM\Column(name="recipients", type="json_array", nullable=true)
*/
private $recipients;
/**
* @var string
*
* @ORM\Column(name="toString", type="string", nullable=true)
*/
private $toString;
/**
* @var array
*
* @ORM\Column(name="cc", type="json_array", nullable=true)
*/
private $cc;
/**
* @var array
*
* @ORM\Column(name="bcc", type="json_array", nullable=true)
*/
private $bcc;
/**
* @var string
*
* @ORM\Column(name="subject", type="string", length=255, nullable=true)
*/
private $subject;
/**
* @var \DateTime
*
* @ORM\Column(name="date", type="datetime")
*/
private $date;
/**
* @var string
*
* @ORM\Column(name="content", type="text", nullable=true)
*/
private $content;
/**
* @var
*
* @ORM\OneToMany(targetEntity="MIP\CRMBundle\Entity\File", mappedBy="mail", cascade={"persist", "remove"})
* @ORM\JoinColumn(name="file_id", referencedColumnName="id", nullable=true)
*/
protected $files;
/**
* @var ArrayCollection
*/
private $attached;
/**
* @var MailBox
* @ORM\ManyToOne(targetEntity="MailBox", inversedBy="mails")
* @ORM\JoinColumn(name="mailBox_id", referencedColumnName="id")
*/
private $mailBox;
/**
* @var LabelSticker
*
* @ORM\ManyToMany(targetEntity="\MIP\MailBundle\Entity\LabelSticker", mappedBy="mails")
*/
private $labels;
/**
* @var boolean
*/
private $readed;
/**
* @var boolean
*/
private $sent;
/**
* Constructor
* @param MailBox $mailbox
* @param boolean $readed
*/
public function __construct($mailbox, $readed)
{
$this->files = new ArrayCollection();
$this->date = new \DateTime('now');
$this->mailBox = $mailbox;
$this->readed = $readed;
}
Thanks for your help !