Ich habe PHP IMAP für die folgenden Aufgaben verwendet:
- Alte Briefe aus Postfächern entfernen . Leider können Sie in der Systemsteuerung des G Suite-Unternehmenskontos den Zeitraum für das Löschen von Nachrichten aus allen Postfächern der Organisation erst nach N Tagen nach Erhalt konfigurieren. Ich muss Briefe jedoch nur in bestimmten Postfächern und nach einer bestimmten Anzahl von Tagen nach Erhalt löschen.
- Buchstaben filtern, analysieren und markieren . Viele Briefe werden automatisch von unserer Website gesendet, von denen einige die Adressaten nicht erreichen, über die dementsprechend Berichte eingehen. Es ist notwendig, diese Berichte abzufangen, zu zerlegen, einen Kunden per E-Mail zu finden und einen lesbaren Brief für den Manager zu erstellen, damit er den Kunden kontaktieren und die Relevanz der E-Mail-Adresse klären kann.
Wir werden diese beiden Aufgaben mithilfe der Google Mail-API in diesem Artikel lösen (und gleichzeitig den Zugriff für unsichere Anwendungen in den Postfacheinstellungen deaktivieren, die für PHP IMAP aktiviert waren, und tatsächlich an einem schrecklichen Tag im Februar 2021 aufhören zu arbeiten). Wir werden das sogenannte Dienstkonto der Google Mail-Anwendung verwenden, das es bei entsprechender Konfiguration ermöglicht, eine Verbindung zu allen Postfächern der Organisation herzustellen und darin Aktionen auszuführen.
1. Erstellen Sie ein Projekt in der Google API-Entwicklerkonsole
Mit Hilfe dieses Projekts führen wir eine API-Interaktion mit Google Mail durch und erstellen darin dasselbe Dienstkonto.
So erstellen Sie ein Projekt:
- Gehen Sie zur Google API-Entwicklerkonsole und melden Sie sich als G Suite-Administrator an (na ja, oder wer ist Ihr Benutzer dort mit allen Rechten)?
- Wir suchen die Schaltfläche "Projekt erstellen".
Ich habe hier gefunden:
Und dann hier:
Geben Sie den Projektnamen ein und speichern Sie:
Projekterstellung
- Gehen Sie zum Projekt und klicken Sie auf die Schaltfläche "API und Dienste aktivieren":
Aktivieren Sie API und Dienste
Auswählen der Google Mail-API
2. Erstellen und konfigurieren Sie ein Dienstkonto
Dazu können Sie das offizielle Handbuch verwenden oder weiterlesen:
- Gehen Sie zu unserer hinzugefügten Google Mail-API, klicken Sie auf die Schaltfläche "Anmeldeinformationen erstellen" und wählen Sie "Dienstkonto":
Erstellung eines Dienstkontos
Füllen Sie etwas aus und klicken Sie auf "Erstellen":
Dienstkontoinformationen
Alles andere kann leer gelassen werden:
Zugriffsrechte für das Dienstkonto
- , . G Suite, « — API».
API
- « »:
«», « » , « OAuth» — :
- https://mail.google.com/ -
- https://www.googleapis.com/auth/gmail.modify -
- https://www.googleapis.com/auth/gmail.readonly -
- https://www.googleapis.com/auth/gmail.metadata -
- « G Suite»:
Geben Sie auch den Namen Ihres Produkts in das Feld unten ein.
- Jetzt müssen Sie einen Dienstkontoschlüssel erstellen: Dies ist eine Datei, die in Ihrer Anwendung verfügbar sein sollte. Er wird in der Tat für die Autorisierung verwendet.
Folgen Sie dazu auf der Seite "Anmeldeinformationen" Ihres Projekts dem Link "Dienstkonten verwalten":
Referenzen
und wählen Sie "Aktionen - Schlüssel erstellen", geben Sie Folgendes ein: JSON:
Service Account Management
Danach wird eine Schlüsseldatei generiert und auf Ihren Computer heruntergeladen, die in Ihrem Projekt abgelegt und beim Aufrufen der Google Mail-API darauf zugegriffen werden muss.
Damit ist die Konfiguration der Google Mail-API abgeschlossen. Dann wird ein kleiner Teil meines Kakao-Codes vorhanden sein und die Funktionen implementieren, die bisher von der IMAP-PHP-Erweiterung gelöst wurden.
3. Schreiben Sie den Code
Es gibt eine recht gute offizielle Dokumentation ( Klicken und Klicken ) für die von mir verwendete Google Mail-API . Aber da ich angefangen habe, ein detailliertes Handbuch zu schreiben, werde ich meinen eigenen Kakaocode anhängen.
Also installieren wir zuerst die Google Client Library (apiclient) mit Composer:
composer require google/apiclient
(Zuerst habe ich als echter Literaturexperte die Version 2.0 des API-Clients installiert, wie in PHP Quickstart angegeben , aber beim ersten Start fielen alle möglichen Vornings und Alarme auf PHP 7.4 Daher rate ich Ihnen nicht, dasselbe zu tun.)
Anschließend schreiben wir anhand von Beispielen aus der offiziellen Dokumentation eine eigene Klasse für die Arbeit mit Google Mail, wobei wir nicht vergessen, die Schlüsseldatei des Dienstkontos anzugeben:
Klasse für die Arbeit mit Google Mail
<?php
// Gmail
class GmailAPI
{
private $credentials_file = __DIR__ . '/../Gmail/credentials.json'; //
// ---------------------------------------------------------------------------------------------
/**
* Google_Service_Gmail Authorized Gmail API instance
*
* @param string $strEmail
* @return Google_Service_Gmail Authorized Gmail API instance
* @throws Exception
*/
function getService(string $strEmail){
//
try{
$client = new Google_Client();
$client->setAuthConfig($this->credentials_file);
$client->setApplicationName('My Super Project');
$client->setScopes(Google_Service_Gmail::MAIL_GOOGLE_COM);
$client->setSubject($strEmail);
$service = new Google_Service_Gmail($client);
}catch (Exception $e) {
throw new \Exception(' getService: '.$e->getMessage());
}
return $service;
}
// ---------------------------------------------------------------------------------------------
/**
* ID
*
* @param Google_Service_Gmail $service Authorized Gmail API instance.
* @param string $strEmail
* @param array $arrOptionalParams
* Gmail after: 2020/08/20 in:inbox label:
* q $opt_param
* @return array ID array('arrErrors' => $arrErrors),
* @throws Exception
*/
function listMessageIDs(Google_Service_Gmail $service, string $strEmail, array $arrOptionalParams = array()) {
$arrIDs = array(); // ID
$pageToken = NULL; //
$messages = array(); //
//
$opt_param = array();
// , Gmail q
if (count($arrOptionalParams)) $opt_param['q'] = str_replace('=', ':', http_build_query($arrOptionalParams, null, ' '));
// , ,
do {
try {
if ($pageToken) {
$opt_param['pageToken'] = $pageToken;
}
$messagesResponse = $service->users_messages->listUsersMessages($strEmail, $opt_param);
if ($messagesResponse->getMessages()) {
$messages = array_merge($messages, $messagesResponse->getMessages());
$pageToken = $messagesResponse->getNextPageToken();
}
} catch (Exception $e) {
throw new \Exception(' listMessageIDs: '.$e->getMessage());
}
} while ($pageToken);
// ID
if (count($messages)) {
foreach ($messages as $message) {
$arrIDs[] = $message->getId();
}
}
return $arrIDs;
}
// ---------------------------------------------------------------------------------------------
/**
* ID batchDelete
*
* @param Google_Service_Gmail $service Authorized Gmail API instance.
* @param string $strEmail
* @param array $arrIDs ID listMessageIDs
* @throws Exception
*/
function deleteMessages(Google_Service_Gmail $service, string $strEmail, array $arrIDs){
// 1000 , batchDelete
$arrParts = array_chunk($arrIDs, 999);
if (count($arrParts)){
foreach ($arrParts as $arrPartIDs){
try{
//
$objBatchDeleteMessages = new Google_Service_Gmail_BatchDeleteMessagesRequest();
//
$objBatchDeleteMessages->setIds($arrPartIDs);
//
$service->users_messages->batchDelete($strEmail,$objBatchDeleteMessages);
}catch (Exception $e) {
throw new \Exception(' deleteMessages: '.$e->getMessage());
}
}
}
}
// ---------------------------------------------------------------------------------------------
/**
* get
*
* @param Google_Service_Gmail $service Authorized Gmail API instance.
* @param string $strEmail
* @param string $strMessageID ID
* @param string $strFormat The format to return the message in.
* Acceptable values are:
* "full": Returns the full email message data with body content parsed in the payload field; the raw field is not used. (default)
* "metadata": Returns only email message ID, labels, and email headers.
* "minimal": Returns only email message ID and labels; does not return the email headers, body, or payload.
* "raw": Returns the full email message data with body content in the raw field as a base64url encoded string; the payload field is not used.
* @param array $arrMetadataHeaders When given and format is METADATA, only include headers specified.
* @return object Message
* @throws Exception
*/
function getMessage(Google_Service_Gmail $service, string $strEmail, string $strMessageID, string $strFormat = 'full', array $arrMetadataHeaders = array()){
$arrOptionalParams = array(
'format' => $strFormat // ,
);
// - metadata,
if (($strFormat == 'metadata') and count($arrMetadataHeaders))
$arrOptionalParams['metadataHeaders'] = implode(',',$arrMetadataHeaders);
try{
$objMessage = $service->users_messages->get($strEmail, $strMessageID,$arrOptionalParams);
return $objMessage;
}catch (Exception $e) {
throw new \Exception(' getMessage: '.$e->getMessage());
}
}
// ---------------------------------------------------------------------------------------------
/**
* ,
*
* @param Google_Service_Gmail $service Authorized Gmail API instance.
* @param string $strEmail
* @return object $objLabels - -
* @throws Exception
*/
function listLabels(Google_Service_Gmail $service, string $strEmail){
try{
$objLabels = $service->users_labels->listUsersLabels($strEmail);
return $objLabels;
}catch (Exception $e) {
throw new \Exception(' listLabels: '.$e->getMessage());
}
}
// ---------------------------------------------------------------------------------------------
/**
* ()
*
* @param Google_Service_Gmail $service Authorized Gmail API instance.
* @param string $strEmail
* @param string $strMessageID ID
* @param array $arrAddLabelIds ID ,
* @param array $arrRemoveLabelIds ID ,
* @return object Message -
* @throws Exception
*/
function modifyLabels(Google_Service_Gmail $service, string $strEmail, string $strMessageID, array $arrAddLabelIds = array(), array $arrRemoveLabelIds = array()){
try{
$objPostBody = new Google_Service_Gmail_ModifyMessageRequest();
$objPostBody->setAddLabelIds($arrAddLabelIds);
$objPostBody->setRemoveLabelIds($arrRemoveLabelIds);
$objMessage = $service->users_messages->modify($strEmail,$strMessageID,$objPostBody);
return $objMessage;
}catch (Exception $e) {
throw new \Exception(' modifyLabels: '.$e->getMessage());
}
}
// ---------------------------------------------------------------------------------------------
}
Wenn wir mit Google Mail interagieren, rufen wir zuerst die Funktion getService ($ strEmail) der GmailAPI-Klasse auf, die ein "autorisiertes" Objekt für die Arbeit mit dem Postfach $ strEmail zurückgibt. Außerdem wird dieses Objekt bereits an eine andere Funktion übergeben, um die von uns benötigten Aktionen direkt auszuführen. Alle anderen Funktionen in der GmailAPI-Klasse führen bereits bestimmte Aufgaben aus:
- listMessageIDs - Findet Nachrichten gemäß den angegebenen Kriterien und gibt ihre ID zurück (die an die Google Mail-API-Funktion listUsersMessages übergebene Suchzeichenfolge muss der Suchzeichenfolge in der Mailbox-Weboberfläche ähnlich sein).
- deleteMessages - löscht Nachrichten mit übergebenen IDs (die BatchDelete-API-Google Mail-Funktion löscht nicht mehr als 1000 Nachrichten in einem Durchgang, sodass ich das an die Funktion übergebene ID-Array in mehrere Arrays mit jeweils 999 Buchstaben aufteilen und den Löschvorgang mehrmals durchführen musste).
- getMessage - Ruft alle Informationen zu der Nachricht mit der an sie übergebenen ID ab.
- listLabels - Gibt eine Liste der Flags in der Mailbox zurück (ich habe sie verwendet, um die ID des Flags abzurufen, das ursprünglich in der Mailbox-Weboberfläche erstellt wurde und den gewünschten Nachrichten zugewiesen ist.)
- modifyLabels - Fügen Sie der Nachricht Flags hinzu oder entfernen Sie sie
Als nächstes haben wir die Aufgabe, alte Briefe in verschiedenen Postfächern zu löschen. Gleichzeitig berücksichtigen wir, dass alte Briefe für jedes Postfach vor einigen Tagen eingegangen sind. Um diese Aufgabe zu erfüllen, schreiben wir das folgende Skript, das täglich von cron ausgeführt wird:
Alte E-Mails entfernen
<?php
/**
* Gmail
*
*/
require __DIR__ .'/../general/config/config.php'; //
require __DIR__ .'/../vendor/autoload.php'; //
//
$arrMailBoxesForClean = array(
'a@domain.com' => 30,
'b@domain.com' => 30,
'c@domain.com' => 7,
'd@domain.com' => 7,
'e@domain.com' => 7,
'f@domain.com' => 1
);
$arrErrors = array(); //
$objGmailAPI = new GmailAPI(); // GMail
// ,
foreach ($arrMailBoxesForClean as $strEmail => $intDays) {
try{
//
$service = $objGmailAPI->getService($strEmail);
//
$arrParams = array('before' => date('Y/m/d', (time() - 60 * 60 * 24 * $intDays)));
// ,
$arrIDs = $objGmailAPI->listMessageIDs($service,$strEmail,$arrParams);
// ID $arrIDs
if (count($arrIDs)) $objGmailAPI->deleteMessages($service,$strEmail,$arrIDs);
//
unset($service,$arrIDs);
}catch (Exception $e) {
$arrErrors[] = $e->getMessage();
}
}
if (count($arrErrors)){
$strTo = 'my_email@domain.com';
$strSubj = ' ';
$strMessage = ' :'.
'<ul><li>'.implode('</li><li>',$arrErrors).'</li></ul>'.
'<br/>URL: '.filter_input(INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL);
$objMailSender = new mailSender();
$objMailSender->sendMail($strTo,$strSubj,$strMessage);
}
Das Skript stellt eine Verbindung zu jedem angegebenen Postfach her, wählt alte Buchstaben aus und löscht sie.
Die Aufgabe, Berichte für den Manager über nicht zugestellte E-Mails basierend auf automatischen Berichten zu generieren, wird durch das folgende Skript gelöst:
E-Mails filtern und markieren
<?php
/*
* a@domain.com
* , : : mailer-daemon@googlemail.com
* . , b@domain.com
*
*/
require __DIR__ .'/../general/config/config.php'; //
require __DIR__ .'/../vendor/autoload.php'; //
$strEmail = 'a@domain.com';
$strLabelID = 'Label_2399611988534712153'; // reportProcessed -
//
$arrParams = array(
'from' => 'mailer-daemon@googlemail.com', //
'in' => 'inbox', //
'after' => date('Y/m/d', (time() - 60 * 60 * 24)), //
'has' => 'nouserlabels' //
);
$arrErrors = array(); //
$objGmailAPI = new GmailAPI(); // GMail
$arrClientEmails = array(); // ,
try{
//
$service = $objGmailAPI->getService($strEmail);
// ,
$arrIDs = $objGmailAPI->listMessageIDs($service,$strEmail, $arrParams);
// 'X-Failed-Recipients', ,
if (count($arrIDs)){
foreach ($arrIDs as $strMessageID){
//
$objMessage = $objGmailAPI->getMessage($service,$strEmail,$strMessageID,'metadata',array('X-Failed-Recipients'));
//
$arrHeaders = $objMessage->getPayload()->getHeaders();
//
foreach ($arrHeaders as $objMessagePartHeader){
if ($objMessagePartHeader->getName() == 'X-Failed-Recipients'){
$strClientEmail = mb_strtolower(trim($objMessagePartHeader->getValue()), 'UTF-8');
if (!empty($strClientEmail)) {
if (!in_array($strClientEmail, $arrClientEmails)) $arrClientEmails[] = $strClientEmail;
}
// reportProcessed,
$objGmailAPI->modifyLabels($service,$strEmail,$strMessageID,array($strLabelID));
}
}
}
}
unset($service,$arrIDs,$strMessageID);
}catch (Exception $e) {
$arrErrors[] = $e->getMessage();
}
// , ,
if (count($arrClientEmails)) {
$objClients = new clients();
// email
$arrAllClientsEmails = $objClients->getAllEmails();
foreach ($arrClientEmails as $strClientEmail){
$arrUsages = array();
foreach ($arrAllClientsEmails as $arrRow){
if (strpos($arrRow['email'], $strClientEmail) !== false) {
$arrUsages[] = ' email "<a href="'.MANAGEURL.'?m=admin&sm=clients&edit='.$arrRow['s_users_id'].'">'.$arrRow['name'].'</a>"';
}
if (strpos($arrRow['email2'], $strClientEmail) !== false) {
$arrUsages[] = ' email "<a href="'.MANAGEURL.'?m=admin&sm=clients&edit='.$arrRow['s_users_id'].'">'.$arrRow['name'].'</a>"';
}
if (strpos($arrRow['site_user_settings_contact_email'], $strClientEmail) !== false) {
$arrUsages[] = ' email "<a href="'.MANAGEURL.'?m=admin&sm=clients&edit='.$arrRow['s_users_id'].'">'.$arrRow['name'].'</a>"';
}
}
$intUsagesCnt = count($arrUsages);
if ($intUsagesCnt > 0){
$strMessage = ' <span style="color: #000099;">'.$strClientEmail.'</span><br/>
';
if ($intUsagesCnt == 1){
$strMessage .= ' '.$arrUsages[0].'<br/>';
}else{
$strMessage .= ':<ul>';
foreach ($arrUsages as $strUsage){
$strMessage .= '<li>'.$strUsage.'</li>';
}
$strMessage .= '</ul>';
}
$strMessage .= '<br/>, .<br/><br/>
, ';
if (empty($objMailSender)) $objMailSender = new mailSender();
$objMailSender->sendMail('b@domain.com',' email ',$strMessage);
}
}
}
if (count($arrErrors)){
$strTo = 'my_email@domain.com';
$strSubj = ' ';
$strMessage = ' :'.
'<ul><li>'.implode('</li><li>',$arrErrors).'</li></ul>'.
'<br/>URL: '.filter_input(INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL);
if (empty($objMailSender)) $objMailSender = new mailSender();
$objMailSender->sendMail($strTo,$strSubj,$strMessage);
}
Dieses Skript stellt wie das erste eine Verbindung zum angegebenen Postfach her, wählt die erforderlichen Briefe aus (Berichte über nicht zugestellte Nachrichten) ohne Flag aus, findet im Brief die E-Mail-Adresse, an die der Brief gesendet werden soll, und markiert diesen Brief mit dem Flag "Verarbeitet" ... Anschließend werden Manipulationen mit der gefundenen E-Mail-Adresse durchgeführt, wodurch ein für Menschen lesbarer Brief an den verantwortlichen Mitarbeiter gebildet wird.
Die Quellen sind auf GitHub verfügbar .
Das ist alles, was ich in diesem Artikel erzählen wollte. Danke fürs Lesen! Wenn mein Code in Ihren Augen gestochen hat, rollen Sie einfach den Spoiler auf oder schreiben Sie Ihre Kommentare - ich freue mich über konstruktive Kritik.