Eingehende E-Mails mit Ticket-ID automatisch dem Ticket zuweisen

Da der Rasperry Pi in der Regel über keine öffentliche E-Mail-Adresse verfügt gibt es auch die Möglichkeit über einen Cronjob eingehende E-Mails eines IMAP-Kontos regelmäßig auszulesen und nach einer Redmine-Ticket-Nummer im Betreff zu suchen. Wenn eine Ticket-Nummer gefunden wurde, kann das Ticket um den Inhalt (Body) der E-Mail als „note“ ergänzt werden.

Voraussetzungen: Für die Nutzung des folgenden Scripts ist die vorherige Einbindung der folgenden beiden Klassen notwendig:

Die Klasse „Redmine“ wird nun um die Zuordnung von „notes“ zum Ticket ergänzt:

class.RedmineEmailGrapper.php
class RedmineEmailGrabber extends Redmine
{
    /**
     * @param string $subject
     * @return int
     */
    public function getTicketIdFromSubject( $subject )
    {
        $pattern = '/([\w\s]*)\s-\s[A-z]*\s#(?P<TicketId>\d*)/';
 
        if( preg_match( $pattern, $subject, $matches ) )
        {
            if( count( $matches ) === 4 )
            {
                return $matches['TicketId'];
            }
        }
 
        return 0;
    }
 
    /**
     * @param integer $id
     * @param string $note
     * @throws Exception
     */
    public function addNoteToIssue( $id, $note )
    {
        $issue = $this->getIssue( $id );
        $issue->notes = substr( $note, 0, 3000 ); // ab 3.000 Zeichen gibt es einen "500 internal Server Error"
        $this->updateIssue( $issue, $id );
    }
}

Nun kann das IMAP-Postfach ausgelesen werden und der Betreff der E-Mails nach Ticket-ID's durchsucht werden. Im Erfolgsfall findet die Zuordnung statt. Hier also der eigentliche Cronjob, der in einem bestimmten Intervall (z. B. alle 15 Minuten) das IMAP-Postfach durchsucht:

$imap = new imap();
$emails = $imap->getEmails( true ); // nur ungelesene E-Mails ansehen
 
if( count( $emails ) > 0 ) // nur, wenn ungelesene E-Mails gefunden wurden
{
    $grabber = new RedmineEmailGrabber();
 
    foreach( $emails as $email ) // jede E-Mail ansehen
    {
        $ticketId = $grabber->getTicketIdFromSubject( $email->subject );
 
        if( $ticketId > 0 ) // wenn eine Ticket-ID gefunden wurde
        {
            $body = $imap->getEmailBody( $email->uid ); // body aus E-Mail lesen
            $grabber->addNoteToIssue( $ticketId, $body ); // neue Notiz erstellen
        }
    }
}
 
$imap->close();