Menu
Is free
check in
the main  /  Multimedia / Pull out letters from the mail. We work with the imap protocol

Pull out letters from the mail. We work with the imap protocol

One of the possible IMAP applications features is the creation of a postal demone, which will manage the subscription and outpiration users from your mailing list. To implement this task, two methods are usually used in mailinglocks. The first suggests that the user should go to a certain page and confirm its actions, the second requires sending a letter. The second also requires the processing script to be regularly launched CRON DAEMON? OM. Because of this, it is not so popular as the first way.

But, as you can see, the most serious newsletters use the second method. Therefore, if you have the ability to use CROND, use it.

Actually, it is not so difficult to understand the functions. The person who used to work for the RNR, without difficulty, how to work with them. Some difficulties may arise with the analysis of the headers of letters that will process the script.

The algorithm of the work of the script itself is easy. The demon establishes a connection to the mail server, and checks the presence of letters on it. In case there are no letters, the script work stops.
If there are letters, there is a parsing of the headers of the first letter. You can watch the FROM and SUBJECT fields. If the Subject field contains one of two permissible header options (subscription or recording), the record that corresponds to the FROM field is either becoming active (confirmed) or removed from the table. In both cases, the address specified in the FROM field is sent to the appropriate notification of the script action. After that, the letter is marked for removal. If Subject does not contain permissible topics, an error notification is sent, and the letter is also marked for removal. Then the script moves to the next letter.
Having finished the analysis of all letters, he cleans the box.

I will not tire the reader in block diagrams, so we will immediately move on to business. The imap_open function is used to open the box. Since PNP supports multiple protocols, then it is necessary to explicitly specify which protocol is used to work with the drawer. In our case, it is POP3 to 110 port (standard). We assign the result of the script to the $ MY_BOX script.


In the future, you will see that this variable will be used pratically in all IMAP features. Next, check the box for letters. The verification performs the IMAP_NUM_MSG function.

$ n \u003d imap_num_msg ($ MY_BOX);

As a result, the variable $ n will contain the number of letters in the box. The number it can be either more zero, or equal to it (if the box is empty).
If there are letters, then cycle while We carry out the analysis of letters, consistently increasing the email number per unit. Please note that the first letter in the box will have number 0, as, and the first element of the array.
To increase the letter number, assign a variable $ M value 0, and then under conditions of the cycle, we increase it per unit $ M ++.

To parse the headlines of interest to us, two functions are enough: imap_header and imap_fetch_overview. To perform each of them, in addition to the drawer, you need to specify the letter number. In our case, it will be equal to the $ m variable.

IMAP_Header Returns an object as a result of execution containing exhaustive information about the header of the letter. Among other things, this object contains an array of the FROM, which contains four values. This is Personal, ADL, Mailbox and Host. We are only interested in Mailbox and Host. Substituting them, we get the address from which the letter was sent.


$ H \u003d $ H -\u003e FROM;
a.
foreach ($ H As $ k \u003d\u003e $ V) (
$ Mailbox \u003d $ V -\u003e Mailbox;
$ Host \u003d $ V -\u003e HOST;
$ Personal \u003d $ V -\u003e Personal;
$ email \u003d $ Mailbox. ? @ ¬. $ HOST;

Imap_fetch_overview - will allow us to know the subject of the letter. For the same purposes it would be possible to use IMAP_Header but for a number reasons for that, sometimes it may not work. From the array that returns this function, we only need the Subject field


Foreach ($ s AS $ k \u003d\u003e $ V) (
$ subj \u003d $ v -\u003e subject;
}

Further, our actions are reduced to pull out email from the base, and if you have it there, mark the entire string with this entry as "verified" or delete. Suppose that after filling out the mailing form on the site, the subscriber is assigned status 0, and after confirming the subscription, it changes to 1.

if ($ subj \u003d\u003d "Subscribe") (
mySQL_Query ( "Update Subscribe Set Stat \u003d 1 WHERE Email \u003d $ My_Email");

}
mySQL_Query ( "Delete from Subscribe WHERE Email \u003d $ My_Email");
$ del \u003d imap_delete ($ MY_BOX, $ M);
}
ELSE (
$ del \u003d imap_delete ($ MY_BOX, $ M);
}

As mentioned above, after performing all actions, the script cleans the box.


This simplest program, only a demonstration that you can write not only dynamically changing sites, but the services that the user are not visible at all can be written. Of course, in terms of writing scripts for Shell, RNR is not applicable, unlike its competitor Perl, but nevertheless ...

Listing the entire program with the exception of the connection parameters with the base (DB.PHP):

include "db.php";
$ My_Box \u003d imap_open ("(you.pop.host/pop3:110)", "login", "password");
$ n \u003d imap_num_msg ($ MY_BOX);
$ m \u003d 0;
$ add_text \u003d "

Thanks for confirming your subscription ";
$ add_sbj \u003d "you added!" ;
$ Del_Text \u003d "

Sorry but this mailbox is used
Only to administer mailing ";
$ err_sbj \u003d "error";
$ Headers \u003d. "From: Subscribe Robot

X-Mailer: PHP4

Content-Type: Text / Plain; Charset \u003d UTF-8
" ;
if ($ n! \u003d 0) (
While ($ M ++< $n ) {
$ H \u003d imap_header ($ MY_BOX, $ M);
$ s \u003d imap_fetch_overview ($ My_Box, $ M);
$ H \u003d $ H -\u003e FROM;
Foreach ($ H As $ k \u003d\u003e $ V) (
$ Mailbox \u003d $ V -\u003e Mailbox;
$ Host \u003d $ V -\u003e HOST;
$ Personal \u003d $ V -\u003e Personal;
$ email \u003d $ Mailbox. "@". $ HOST;
$ MY_EMAIL \u003d mysql_escape_string ($ email);
}
Foreach ($ s AS $ k \u003d\u003e $ V) (
$ subj \u003d $ v -\u003e subject;
}
if ($ subj \u003d\u003d "Subscribe") (
mySQL_Query ( "Update Table Set Stat \u003d 1 WHERE Email \u003d $ My_Email");
// Print MySQL_ERROR ();
$ del \u003d imap_delete ($ MY_BOX, $ M);
mail ($ email, $ add_sbj, $ add_text, $ Headers);
}
Elseif ($ subj \u003d\u003d "unsubscribe") (
mySQL_Query ( "Delete from Table WHERE Email \u003d $ My_Email");
$ del \u003d imap_delete ($ MY_BOX, $ M);
mail ($ email, $ del_sbj, $ del_text, $ Headers);
}
ELSE (
$ del \u003d imap_delete ($ Open_Box, $ M);
mail ($ email, $ er_sbj, $ er_text, $ Headers);
}
}
$ Clear \u003d imap_Expunge ($ My_Box);
}
?>


Email - This is the most important tool for sharing information and if you are using it for work, then surely come across the situation: a letter comes to the mail, which contains the data necessary for the processing creak. We will talk about Yandex mail - in this article I will share with you, dear readers, experience how to get letters from the box, we will also analyze the option when there is an invested file in the letter - how to find it and eventually download it for further manipulations .

I myself encountered this task for a long time, and then, if there is a small experience with the Yandex postal programs, I spent a lot of time and nerves to achieve the desired result. My first mistake was that, like many web developers, I began to intensively search for similar examples on the network, but did not use the help of Yandex. Yes, there is useful information, although it is very small, but it is quite important for writing this kind of script (it will be below). At that time, it was necessary to write a script, the essence of which was reduced: the Customer's Mail came to the Customer's mail a letter with the price of goods in the XLS format once a day, it was necessary to process it (to paint and compare with the data from the DB Online store and, depending on the result, That update somewhere, disable or enable).

And the first thing we will do before writing the script is to make our action plan, which will consist of nine items:

  1. Configure mail to gain access via postal protocols;
  2. Note the structure itself Php applications and determine the encoding of files;
  3. We will get acquainted with the IMAP postal protocol and its capabilities;
  4. We connect to Yandex mail through the login and password of the account and track the error at this stage;
  5. Process the header of the letter;
  6. We obtain and process the body of the letter;
  7. We get and save nested files;
  8. We visualize the work done;
  9. Make conclusions.

The theme is quite voluminous, but I will try to set out everything is most compact and understandable. Perhaps proceed.

Setting mail

Go to your mail and go into the settings, as shown below in the screenshot:



Now we have come to settings by mail through the IMAP and POP3 protocols:


Here, many will see the picture as the image above, but I came across, and more than once, when access is disabled. Therefore, if you have other settings, put the ticks as in the screenshot, for us the main thing to allow access via the IMAP protocol.

Application structure and its encoding

In this example, we will not come up with a complex application structure, as it is not needed, and add only what is needed (I work in the Sublime Text editor):


  • tMP - folder in which we will download nested files from the letter if they are;
  • .htaccess - setting up the server part, if you have a Apache server;
  • functions.php - here will add our functions;
  • main.css - style file;
  • index.php - application entry point;

The encoding will use UTF-8 and therefore immediately fill the file.htaccess next rows:

AddDefaultCharset UTF-8 AddCarset UTF-8 * CHARSETSOURCEENC UTF-8 CHARSETDEFAULT UTF-8

IMAP protocol

Returning to the first item it can be seen that it is also possible to work with the Yandex mail through the POP3 protocol. So why exactly imap? From these two IMAP ducts is a newer and alternative POP3, therefore, he has a number of advantages (they can be studied by using Wikipedia), but in our case the choice was influenced only that he was new. Personally, I do not see a special difference that use under specific task receiving a letter. If for any reason you need to use the POP3 protocol, then all the functions that apply to IMAP will work for it.

Connect to Yandex mail using the IMAP protocol

In order to connect to mail, we need to know three parameters: login mail, its password and address mail Server. If there are no problems with two parameters, then the second can be found in the help of Yandex. About it (I had a problem) I was higher and wrote a mass of examples, where the third parameter is not correct and, imagine that there are errors at least at the connection stage - it is at least unpleasant. I will not walk around and about and immediately give a direct link to the Yandex page - setting postal programs . Here's actually what we need to connect:


Now you can go directly to the code itself:

Header ("Content-Type: text / html; charset \u003d utf-8"); Error_Reporting (0); Require_ONCE ("Functions.php"); $ mail_login \u003d "yandex_pot"; $ Mail_Password \u003d "Password_Text"; $ Mail_imap \u003d "(imap.yandex.ru:993/imap/ssl)"; // List of accounted types of files of $ Mail_FileTypes \u003d Array ("MSWORD"); $ Connection \u003d imap_open ($ Mail_imap, $ Mail_Login, $ Mail_Password); If ("$ Connection) (Echo (" Error Connection with Mail - ". $ Mail_login); exit;) ELSE ($ MSG_NUM \u003d imap_num_msg ($ Connection); $ Mails_Data \u003d Array (); for ($ i \u003d 1; $ I.<= $msg_num; $i++){ /* Работать с каждым письмом из IMAP-потока будем тут */ } } imap_close($connection);

First, further specify the UTF-8 encoding using the header and turn off the error mapping. Connect the file Functions.php and specify the settings that were addressed above. In the $ Mail_FileTypes array we prescribe file formats that we need. So it was decided to make the unnecessary garbage, and receive specific files. Mail connection occurs using the IMAP_Open () function, which, with a good execution, returns an IMAP stream, and with the failure - false (but if you turn on the error display, then this is not the case). Complete work with streams using the IMAP_Close () function by passing it the connection indicator. There is an ordinary conditional operator between these two functions.

With a successful connection using IMAP_NUM_MSG (), we learn the number of letters in the mail and add an array to which we put all the necessary data from the stream. Next, a cycle is followed in which each letter will be processed by its number (the numbering occurs from 1) separately.

Processing the header of the letter

To get a letter header, you must use the IMAP_Header () function, the second parameter of which is the letter number:

// Letter Cap $ MSG_Header \u003d imap_header ($ Connection, $ i);

At this stage, we will get an object from which we will pull the data we need while maintaining the $ mails_data array. Here is an example of one of the letters:

This screenshot shows that all data is duplicated, but it does not play a special role, pull, what is more convenient. Much more important is the encoding of the topic of the letter. It can be any or this moment must be controlled. The same situation with the body of the letter and with nested files.

$ mails_data [$ i] ["Time"] \u003d Time ($ MSG_Header-\u003e MailDate); $ Mails_Data [$ i] ["date"] \u003d $ MSG_Header-\u003e MailDate; Foreach ($ MSG_Header-\u003e to As $ Data) ($ Mails_Data [$ i] ["to"] \u003d $ Data-\u003e Mailbox. "@. $ Data-\u003e Host;) Foreach ($ MSG_Header-\u003e From AS $ Data) ($ mails_data [$ i] ["from"] \u003d $ Data-\u003e Mailbox. "@. $ Data-\u003e Host;)

We save in our array: a temporary label, the date of receipt of the letter, the email of the recipient and the sender and go to getting the topic of the letter. To do this, we first first add three functions to Functions.php file:

Function check_utf8 ($ Charset) (IF (STRTOLOWER ($ Charset)! \u003d "UTF-8") (Return False;) Return True;) Function convert_to_utf8 ($ in_charset, $ STR) (RETURN ICONV ($ in_charset), "UTF-8", $ STR);) Function Get_imap_title ($ STR) ($ MIME \u003d imap_mime_header_decode ($ STR); $ title \u003d ""; foreach ($ mime as $ key \u003d\u003e $ M) (if (! check_Utf8 ($ M-\u003e Charset)) ($ title. \u003d convert_to_utf8 ($ M-\u003e CHARSET, $ M-\u003e TEXT);) ELSE ($ title. \u003d $ M-\u003e Text;)) Return $ Title;)

Talk names and, I think it is worth explaining only the last function. It accepts the encoded string and using IMAP_MIME_Header_Decode () decodes it, as a result of which an array of objects is returned, each of which has two Charset properties (encoding) and Text (text topic). Further everything is simple: in the loop checking the encoding, we click on UTF-8 and glue the topic into a single header and return it.

Now let's return to the index.php file and extend the last parameter:

$ mails_data [$ i] ["title"] \u003d get_imap_title ($ MSG_Header-\u003e Subject);

On this processing of the header of the letter will be completed.

We work with a letter of writing

We continue to gradually formed our array with the processed letters data and now, for the body, we need to use two functions:

// Body letter $ MSG_STRUCTURE \u003d IMAP_FETCHSTRUCTURE ($ Connection, $ i); $ msg_body \u003d imap_fetchbody ($ Connection, $ i, 1);

In the first variable $ MSG_STRUCTURE there is a letter structure - this is an object in which you can find a mass useful informationThe example of the part of this object is presented below:

What is important to solve our problem:

  • type is the primary type of letter body, depending on what comes to mail it can change from 0 to 7 (each digit advises its type of content that is in the body of the letter);
  • encoding - Body Transfer Encoder, varies from 0 to 5 (0 - 7bit, 1 - 8bit, 2 - Binary, 3 - Base64, 4 - quoted-printable, 5 - other);
  • parts is an array of parts of the letter that corresponds to the structure of the object level above.

Look in more detail. Consider the PARTS property. The first thing to say is that in the zero cell of this array, there is information corresponding to the text of the letter, and starting with the first - nested files. Also in each object specified Type and in Parameters encoding in the apparent and not explicit form.

The structure of the letter can be hidden invested, at least I had cases when it reached four - five levels, so that it, as they say, disconnect us in the future it will be necessary to write a recursive function.

The second function IMAP_FETCHBODY () extracts a specific part of the letter, most often in the encoded form.

Now add a variable in which we will maintain the processed version of the body of the letter:

$ body \u003d "";

Let's return to the file Functions.php and write a recursive function:

Function Recursive_Search ($ Structure) ($ Encoding \u003d ""; if ($ Structure-\u003e Subtype \u003d\u003d "HTML" || $ STRUCTURE-\u003e Type \u003d\u003d 0) (if ($ STRUCTURE-\u003e PARAMETERS-\u003e ATTRIBUTE \u003d\u003d " Charset ") ($ charset \u003d $ STRUCTURE-\u003e PARAMETERS-\u003e VALUE;) RETURN Array (" Encoding "\u003d\u003e $ Structure-\u003e Encoding," Charset "\u003d\u003e Strtolower ($ charset)," subtype "\u003d\u003e $ structure- \u003e subtype);) ELSE (IF (ISSET ($ Structure-\u003e Parts)) (Return Recursive_Search ($ Structure-\u003e Parts);) ELSE (IF ($ STRUCTURE-\u003e PARAMETERS-\u003e ATTRIBUTE \u003d\u003d "CHARSET") ($ Charset \u003d $ STRUCTURE-\u003e PARAMETERS-\u003e VALUE;) RETURN ARRAY ("ENCODING" \u003d\u003e $ STRUCTURE-\u003e ENCODING, "CHARSET" \u003d\u003e STRTOLOWER ($ charset), "subtype" \u003d\u003e $ structure-\u003e subtype);) ))

The Recursive_Search () function takes one parameter - the letter structure where the properties sequentially checks and pulls three parameters: encoding, charset, subtype. An exit point from recursion is the absence of the property of the PARTS with a zero cell. More to explain here there is nothing more, from the code I think it is clear what is happening.

We will add another feature for contendance of the body of the letter, which will be required in the future:

Function Structure_encoding ($ Encoding, $ MSG_Body) (Case 4: $ Body \u003d IMAP_QPRINT ($ MSG_BODY); Break; Case 3: $ Body \u003d IMAP_BASE64 ($ MSG_Body); Break; Case 2: $ Body \u003d imap_binary ($ msg_body); break; case 1: $ body \u003d imap_8bit ($ msg_body); break; case 0: $ body \u003d $ msg_body; break; default: $ body \u003d ""; break;) Return $ BODY ;)

$ Recursive_Data \u003d Recursive_Search ($ MSG_STRUCTURE); if ($ Recursive_Data ["Encoding"] \u003d\u003d 0 || $ recursive_data ["encoding"] \u003d\u003d 1) ($ body \u003d $ msg_body;) if ($ recursive_data ["encoding"] \u003d\u003d 4) ($ Body \u003d STRUCTURE_ENCODING ($ Recursive_Data ["Encoding"], $ msg_body);) if ($ recursive_data ["encoding"] \u003d\u003d 3) ($ Body \u003d Structure_ENCoding ($ Recursive_Data ["Encoding"], $ msg_body);) if ($ recursive_data ["encoding"] \u003d\u003d 2) ($ Body \u003d Structure_encoding ($ recursive_data ["encoding"], $ msg_body);) if (! check_utf8 ($ recursive_data ["charset"])) ($ Body \u003d convert_to_utf8 ($ recursive_data ["charset"], $ msg_body);)

After we received data from recursion, gradually check the transfer encoding and, depending on this, call the STRUCTURE_ENCODING () function with the corresponding parameters. In the last conditional statement, we consider what we work in UTF-8 and if after all manipulations we will have different from the encoding, recoding.

It remains to be drawn:

$ mails_data [$ i] ["Body"] \u003d base64_encode ($ Body);

In the body, the letter may be, both the usual text and HTML markup with their styles. We encode in BASE64 so that our layout will not go with visualization.

Nested files

Here, smoothly we get to the end of writing our application:

// Nested IF files (ISSET ($ MSG_STRUCTURE-\u003e PARTS)) (for ($ j \u003d 1, $ f \u003d 2; $ j< count($msg_structure->parts); $ J ++, $ F ++) (if (in_array ($ MSG_STRUCTURE-\u003e PARTS [$ J] -\u003e Subtype, $ Mail_FileTypes)) ($ MailS_Data [$ i] ["attachs"] [$ j] ["type"] \u003d $ MSG_STRUCTURE-\u003e PARTS [$ J] -\u003e subtype; $ mails_data [$ i] ["attachs"] [$ j] ["Size"] \u003d $ MSG_STRUCTURE-\u003e PARTS [$ J] -\u003e Bytes; $ mails_data [ $ i] ["attachs"] [$ j] ["name"] \u003d get_imap_title ($ msg_structure-\u003e parts [$ J] -\u003e Parameters-\u003e Value); $ Mails_Data [$ i] ["attachs"] [$ J] ["File"] \u003d STRUCTURE_ENCODING ($ MSG_STRUCTURE-\u003e PARTS [$ J] -\u003e Encoding, IMAP_FETCHBODY ($ Connection, $ i, $ F)); file_put_contents ("TMP /". Iconv ("UTF-8" , "CP1251", $ mails_data [$ i] ["attachs"] [$ J] ["Name"]), $ mails_data [$ i] ["attachs"] [$ j] ["file"]);) ))

A piece responsible for processing an embedded file is much smaller, and now - why exactly. The principle of working with the file is similar to working with the body of the letter, only this stage is starting with the presence in the array of the PARTS properties. Do not forget to cut off unnecessary, turning with the list of types. Using a simple File_Put_Contents () function, we save our file to the server to the TMP folder.

I want to see the result!

In the process of work, we have formed an array with $ mails_data data, and for visualization we will work directly with it. In this article, I used a test letter that I had a mail, let's see what we did in the end:


Here is what kind of something you need to get an array, alas, I had to hide the content of the file for personal reasons. Now go to our HTML markup:

Yandex Mail |<?php echo($mail_login);?>

Yandex Mail (incoming) |

Number of letters:

no letters
$ Mail):?\u003e
Timing Tag:
Date:
To whom:
From:
Subject:
Letter in Base64:
Nested files:
$ ATTACH) :?\u003e
A type:
Size (in bytes):
Name:
Body:

Styles I will not add here, since they do not play a special role, as a result:


And on the server in the TMP folder you will have a file.

Conclusion

Having done all the stages from the article, you achieve due results, but everything is not as easy as it may seem - there are pitfalls that need to be considered. When writing a script for a specific task, you must follow the encoding at all stages, letters can go from various mail, each of which may have their own nuances. It will also be important to take into account that Yandex mail and their documentation periodic is updated, so various sub-clauses may appear to work with postal programs. I have everything on this, I hope you use this article when working with a lower-level version of Yandex Mail.

It is impossible to receive an attachment letter (
If mail is sent with the file - anyone disappears the text of the letter

help me please

It is clear ... if it turns out everything from Yandex on Yandex ...
Type figured out
But that's why other files besides Word, this script does not accept it is not clear ... There is a line MSWORD near the comma and PDF and the FLG and PHG - reads and saves only the Word .... Something like that

Some web applications may require special email for the user. In this case, we can write your own Squirrelmail or RoundCube email code. No matter what you choose, knowledge of Mail IMAP will be useful.

How to work with IMAP in PHP is described on two pages. On the first page, the necessary features for connecting to mail servers and reading messages. On the second page, let's talk about working with email, for example, deleting messages, download applications, etc ...

To demonstrate functionality, code examples that can be used to start the scripts of your own mail client will be used.

URL parameters for calling the necessary functions:

  • fUNC - type of function required (for example: read email, view mailbox, delete message)
  • folder - the name of the mailbox folder for connection (for example: incoming, sent, spam)
  • uID - unique email identifier

Parameters can be obtained using $ _GET and SWITCH can be used to call the appropriate actions.

Connect to the IMAP server

To establish a connection to the IMAP server, we use the IMAP_CONNECT () function, as shown below:

Message path, username and password The necessary parameters for connecting to the server. You can learn about the additional parameters in the manual.

The path to the mailbox is a string that identifies the server and port in curly brackets defines the name of the desired mail folder.

Here are a few rows for folder Incoming postal services:

  • Gmail (IMAP.gmail.com: 993 / IMAP / SSL) INBOX
  • Yahoo (imap.mail.yahoo.com: 993 / imap / ssl) Inbox
  • AOL (IMAP.Aol.com: 993 / IMAP / SSL) INBOX

On some servers no SSL is enabled, in this case you will need to omit the "SSL" from the string. Other servers can use their own certificates in which you must enable "NOVALIDATE-CERT".

With an open connection to the postage server, we can now look at the functions used for the following activities:

  • Displays the list of mailbox folder in your email account
  • Displays the list of email messages in the folder
  • View author's email content

Email folders

Incoming , Posted , Rubbish and Spam - These folders are visible in almost every email account, and users can often create their own folders. In order to view messages in these folders, we must change our connection string. For example, apply "INBOX" (incoming) in the row of the path earlier. If you need to connect to the Spam folder, use something like "spam" (spam) instead. But although it can be listed as Spam In an email account, if you look through the email client, the present name of the folders in the background may be different. We can list all available folders in the account using IMAP_LIST ().

"; foreach ($ folders as $ folder) ($ folder \u003d STR_REPLACE (" (imap.gmail..php? Folder \u003d ". $ folder." & func \u003d view "\u003e". $ Folder. "";) Echo"";

We must transfer the connection descriptor obtained from imap_open () as the original parameter imap_list (). We must also go through the path (without a folder, for example, "INBOX"). As a third parameter, the request of all available folders.

Notification of the message

Each folder contains a list of available email messages, so let's see how we can create a list of messages in our mailbox.

First you need to get the number of messages available using IMAP_NUM_MSG (). Then we can use the IMAP_Header () function to get information for the title of each message.

Let's say if we want the last 20 letters:

($ nummessages - 20); $ i--) ($ Header \u003d imap_header ($ imap, $ i); $ Fromfo \u003d $ header-\u003e from; $ replyinfo \u003d $ header-\u003e reply_to; $ details \u003d array ("fromaddr" \u003d\u003e (ISSET ($ FromInfo-\u003e Mailbox) && ISSET ($ FROMFO-\u003e HOST))? $ Fromfo-\u003e Mailbox. "@". $ Fromfo-\u003e Host: "", "fromname" \u003d\u003e (ISSET)) ? $ Fromfo-\u003e Personal: "", "replyaddr" \u003d\u003e (ISSET ($ replyinfo-\u003e mailbox) && isset ($ replyinfo-\u003e host))? $ replyinfo-\u003e mailbox. "@". $ replyinfo-\u003e Host : "", "ReplyName" \u003d\u003e (ISSET ($ replyto-\u003e personal))? $ replyto-\u003e Personal: "", "subject" \u003d\u003e (ISset ($ Header-\u003e Subject))? $ Header-\u003e Subject : "", "udate" \u003d\u003e (ISset ($ header-\u003e udate))? $ Header-\u003e Udate: ""); $ uid \u003d imap_uid ($ imap, $ i); echo "

    "; Echo"
  • From:". $ details [" fromname "]; echo" ". $ details [" FROMADDR "]."
  • "; Echo"
  • SUBJECT: ". $ details [" subject "] ..php? Folder \u003d". $ Folder. "& UID \u003d". $ uid ..php? folder \u003d ". $ folder." & UID \u003d ". $ UID." & FUNC \u003d DELETE "\u003e Delete
  • "; Echo"
"; }

Compound $ IMAP must be opened in the desired folder. We can then go through the last 20 letters using the number of messages obtained by imap_num_msg (). Communication and email number is given imap_header () to obtain information about the title, which can then be perigate for interesting information from the sender, email address, name, subject, etc.

Please note that the email number from the total number of messages is not a unique identifier for the message. If you have 100 letters in your mailbox, then the last number will be 100, the previous one will be 99, and so on. If you delete a message at number 100, then you get a new message, its number will be 100.

To proceed with the following actions, you need to get a unique identifier for email. Each letter has a unique identifier called UID, which we can get by providing email, the function for the imap_uid () number UID is unique and will not change with time.

View message content

Email reading is not really a simple matter as previous tasks, so you need to use mail classes developed by Mitula Carade. The following three functions for our example are adapted to the class below:

encoding) (Case 3: Return imap_base64 ($ text); Case 4: Return imap_qprint ($ text); Default: Return $ text;)) // Multipart if ($ Structure-\u003e Type \u003d\u003d 1) (Foreach ($ Structure -\u003e Parts as $ index \u003d\u003e $ substruct) ($ prefix \u003d ""; if ($ partnumber) ($ prefix \u003d $ partnumber. "";) $ data \u003d get_part ($ imap, $ uid, $ MimeType, $ Substruct, $ prefix. ($ Index + 1)); if ($ data) (Return $ Data;)))) Return False; ) Function Get_Mime_Type ($ STRUCTURE) ($ PrimaryMimeType \u003d Array ("Text", "Multipart", "Message", "Application", "Audio", "Image", "Video", "Other"); if ($ STRUCTURE -\u003e Subtype) (Return $ PrimaryMimeType [(int) $ STRUCTURE-\u003e TYPE]. "/". $ STRUCTURE-\u003e Subtype;) Return "Text / Plain";)

The GetBody () function receives email content, passing your UID and the IMAP connection. Inside the function, we clarify the GET_PART () function with the content type as text / html. The usual email message is much easier to read. Thus, we first try to find the contents of HTML inside the email.

Then we read the email structure using the IMAP_FETCHSTRUCTURE () function. We changed the library functions to use the UID, instead of passing ft_uid constantly.

Then we get the MIME type of email message using the get_mime_type () function. There are eight MIME types returned by this feature as integers:

  • 0 - TEXT.
  • 1 - Multipart.
  • 2 - Message.
  • 3 - Application
  • 4 - Audio.
  • 5 - image
  • 6 - Video
  • 7 - Other

We turn return to the real type MIME string using MIME type arrays.

Composite messages can have a large number of subtypes, so we are recursively through all subtypes using part of the numbers and receiving e-mail using IMAP_FETCHBODY () when the correct is using Mime-Type.

Then, we use the appropriate decoding function in accordance with the encoding of the message type and extend the content. Full list of available coding types:

  • 0 - 7bit
  • 1 - 8bit
  • 2 - Binary.
  • 3 - Base64.
  • 4 - quoted-printable
  • 5 - Other

Conclusion

We finished viewing the basics of connecting to the IMAP server, a list of messages within the available folders, and finished reading the content of the email message. On the next page of the record, it will be described about the functions that can be used to implement the additional functionality of the mail client, for example, deleting messages and processing attachments.

The other day I came to write a small module on PHP, which would allow working with incoming mail. A little in the google I saw that for this task it is suitable for me one of the protocols POP3 and Imap.
But the choice was obvious that I will use IMAP as it is more functional and modern, POP3 protocol.

Now I needed to quickly figure out how to work with IMAP protocols, how to get letters from the Yandex / Google email server.

For more convenient work, I chose the library Phpimap Since it can quickly and easily implements all the tasks you need.

Connect to post server.

Now, when we decided on the choice of the protocol and the choice of the library, we will try to connect to the post server.

For full-fledged PHP work with the IMAP protocol, you need to connect the extension php_imap.dll / imap.so. in the php.ini file.

For the beginning, let's try to connect to Yandex mail as I have the least problems with it.

// Connect the include libraries ("/ phpimap / mailbox.php"); Include ("/ phpimap / incomingmail.php"); // For convenience, create a constant for connecting to the postal server. Define ("Mail_imap_Server", "imap.yandex.ru"); Define ("Mail_imap_Server_Port", 993); Define ("Mail_imap_login", ""); Define ("Mail_imap_pass", "example_pass"); Define ("Mail_imap_path", "(" .mail_imap_server. ":" Mail_imap_Server_Port. "/ imap / ssl) inbox"); $ Mailbox \u003d New Phpimap \\ Mailbox (Mail_imap_path, Mail_imap_Login, Mail_imap_pass, __dir__); Try ($ Mailbox-\u003e getimapstream ();) Catch (Exception $ E) (DIE ($ E-\u003e GetMessage ());)

As we see a class designer Mailbox Takes the following arguments:

  • Mail_imap_path - Together a server address (Mail_imap_Server), a connection port (Mail_imap_Server_Port), a connection type (IMAP) and show that the connection will be encrypted (SSL). After the curly brackets, you specify the folder to which we will connect, in this case to incoming messages (InBox).
  • Mail_imap_login. - Mailbox which will be connected.
  • Mail_imap_pass. - Password (most often it is a password from the mailbox).
  • __Dir__- This is the path to the folder in which the nested files and email messages will be saved.

After that we will check whether our connection was created through the method getimapStream () If for some reason the connection will not be created, then the application throws exclusions with the cause of not a good connection.

It is important to take into account the fact that in the settings of Yandex mail you can disable the possibility of connecting via the IMAP protocol.

Now let's compare the connection to the Gmail mail.

Define ("Mail_imap_Server", "imap.gmail.com"); Define ("Mail_imap_Server_Port", 993); Define ("Mail_imap_login", ""); Define ("Mail_imap_pass", "example_pass"); Define ("Mail_imap_path", "(" .mail_imap_server. ":" Mail_imap_Server_Port. "/ imap / ssl) inbox");

As we see it almost does not differ from the previous connection, but most likely you will have an exception when connecting to the server.
This problem is due to the fact that Gmail IMAP protocol work is disabled by default. You can enable it in the settings in the forwarding tab and POP / IMAP in the access option by IMAP Protocol ⇒ Enable IMAP.

After we have turned on the work on the IMAP protocol, we need create password app. In order for it to be able to create, we need to make two factor authorization for this profile. After that, you can proceed to its creation. When we create a new password for the application, we need to be inserted into the Mail_imap_pass constant for connecting to the server.

Note that when creating a password application, you may not be able to connect to the server it is connected with the fact that this password has not yet been applied finally to the Gmail service usually takes 5-60 minutes.

Data sampling

After a successful connection, we can execute a request to get sweat messages from the server. For this we will use the method searchMailBox (String $ Criteria) which is essentially a wrapper method imap_search.. It is important to understand that the $ Criteria argument is a certain search for the search we need, the method itself returns the identifiers of the elements that subsequently use it for detailed mail information.

$ MailSids \u003d $ Mailbox-\u003e SearchMailbox ("All");

As you already guessed here, we get all messages.
And now let's try to figure it out with other equally important search criteria:

// All posts for 3 days. $ MailSids \u003d $ Mailbox-\u003e SearchMailbox ("SINCE" .DATE ("D-M-Y", STRTOTIME ("- 3 Day")). "" "); // Unread messages for 3 days. $ MailSids \u003d $ Mailbox-\u003e SearchMailbox ("Unseen Since" .date ("D-M-Y", StrTotime ("- 3 Day")). "" "); // Search for messages with such a correspondence in the Text title. $ MailSids \u003d $ Mailbox-\u003e SearchMailbox ("Text" Newsletter "); // Search for messages with such a correspondence in the Body header. $ MailSids \u003d $ Mailbox-\u003e SearchMailbox ("Body" informational message "); // Search by email sender. $ MailSids \u003d $ Mailbox-\u003e SearchMailbox ("from" "); // Get messages on the Subject $ MailSIDS \u003d $ Mailbox-\u003e SearchMailbox ("Subject" updates for your phone ");

This example reflects the basics to use search criteria.

Receiving the information

Now when we have an array of message identifiers, we are ready to process it:

// Get the identifier of the last message from the array. $ ID \u003d END ($ MailSids); // Get an instance of an incomingmail class object that contains information about the message. $ Mail \u003d $ Mailbox-\u003e getmail ($ ID); // Get files embedded to this message if it is. $ Mail-\u003e GetAttachments (); // Display messages. Echo $ Mail-\u003e TextHTML;

So we received messages from our letter and its investments without any problems.

Additional features.

In this library, also the presence of a number of useful methods for more convenient work with postal messages:

Save messages by its ID.

$ Mailbox-\u003e Savemail ($ ID, $ ID. "EML");

We establish messages as unread by its ID.

$ Mailbox-\u003e MarkMailasUnread ($ ID);

We establish messages as read by its ID.

$ Mailbox-\u003e MarkMailasread ($ ID);

Install the message on its ID.

$ Mailbox-\u003e MarkMailasImportant ($ ID);

Delete messages by its ID.

One of the possible IMAP applications features is the creation of a postal demone, which will manage the subscription and outpiration users from your mailing list. To implement this task, two methods are usually used in mailinglocks. The first suggests that the user should go to a certain page and confirm its actions, the second requires sending a letter. The second also requires the processing script to be regularly launched CRON DAEMON-OM. Because of this, it is not so popular as the first way.

But, as you can see, the most serious newsletters use the second method. Therefore, if you have the ability to use CRON, use it.

Actually, it is not difficult to understand the functions. Some difficulties may arise with the analysis of the headers of letters that will process the script.

The algorithm of the work of the script itself is easy. The demon establishes a connection to the mail server, and checks the presence of letters on it. In case there are no letters, the script work stops. If there are letters, there is a parsing of the headers of the first letter. You can watch the FROM and SUBJECT fields. If the Subject field contains one of two permissible header options (subscription or recording), the record that corresponds to the FROM field is either becoming active (confirmed) or removed from the table. In both cases, the address specified in the FROM field is sent to the appropriate notification of the script action. After that, the letter is marked for removal. If Subject does not contain permissible topics, an error notification is sent, and the letter is also marked for removal. Then the script moves to the next letter. Having finished the analysis of all letters, he cleans the box.

The imap_open function is used to open the box. As PHP supports multiple protocols, then it is necessary to explicitly specify which protocol is used to work with the drawer. In our case, it is POP3 to 110 port (standard). We assign the result of the script to the $ MY_BOX script.

$ My_Box \u003d imap_open ("(you.pop.host/pop3:110)", "login", "password");

In the future, you will see that this variable will be used pratically in all IMAP features. Next, check the box for letters. The verification performs the IMAP_NUM_MSG function.

$ n \u003d imap_num_msg ($ MY_BOX);

As a result, the variable $ n will contain the number of letters in the box. The number it can be either more zero, or equal to it (if the box is empty). If there are letters, then in the WHILE cycle, we perform the analysis of letters, consistently increasing the letter number per unit. Please note that the first letter in the box will have number 0, as, and the first element of the array. To increase the letter number, assign a variable $ M value 0, and then under conditions of the cycle, we increase it per unit $ M ++.

To parse the headlines of interest to us, two functions are enough: imap_header and imap_fetch_overview. To perform each of them, in addition to the drawer, you need to specify the letter number. In our case, it will be equal to the $ m variable.

iMAP_Header Returns an object as a result of execution containing exhaustive information about the header of the letter. Among other things, this object contains an array of the FROM, which contains four values. This is Personal, ADL, Mailbox and Host. We are only interested in Mailbox and Host. Substituting them, we get the address from which the letter was sent.

$ H \u003d imap_header ($ MY_BOX, $ M); $ H \u003d $ H-\u003e FROM; Foreach ($ H As $ k \u003d\u003e $ V) ($ Mailbox \u003d $ V-\u003e Mailbox; $ Host \u003d $ V-\u003e Host; $ Personal \u003d $ V-\u003e Personal; $ email \u003d $ Mailbox. "@". $ HOST;

imap_fetch_overview - will allow us to know the subject of the letter. For the same purposes, IMAP_Header could be used, but for a number of reasons it may sometimes not work. From the array that returns this function, we only need the Subject field

$ s \u003d imap_fetch_overview ($ My_Box, $ M); foreach ($ s AS $ k \u003d\u003e $ V) $ subj \u003d $ V-\u003e Subject;

Further, our actions are reduced to pull out email from the base, and in case of having it there, mark the entire string with this entry as, or deleted. Suppose that after filling out the mailing form on the site, the subscriber is assigned status 0, and after confirming the subscription, it changes to 1.

If ($ Subj \u003d\u003d "Subscribe") (mysql_query ("Update Subscribe Set Stat \u003d 1 WHERE Email \u003d $ My_Email"); $ del \u003d imap_delete ($ My_box, $ M); mail ($ email, $ add_sbj, $ add_text , $ Headers);) ELSE if ($ subj \u003d\u003d "unsubscribe") (mysql_query ("Delete from Subscribe Where email \u003d $ My_Email"); $ del \u003d imap_delete ($ My_box, $ M); mail ($ email, $ del_sbj, $ del_text, $ Headers);) ELSE ($ Del \u003d imap_delete ($ My_box, $ M); mail ($ email, $ er_sbj, $ er_text, $ headers);) After performing all actions, the script cleans the box. $ Clear \u003d imap_Expunge ($ My_Box);

This simple program is only a demonstration that you can write not only dynamically changing sites, but also services that are not visible at all.

Listing the entire program with the exception of the connection parameters with the database:

Include "config.php"; // Connection from database $ My_box \u003d imap_open ("(you.pop.host/pop3:110)", "Login", "Password"); $ n \u003d imap_num_msg ($ MY_BOX); $ m \u003d 0; $ add_text \u003d "Thank you for confirming your subscription"; $ add_sbj \u003d "you added!"; $ del_text \u003d "You have been deleted from the mailing list."; $ del_sbj \u003d "DELETE FROM LIST"; $ err_text \u003d "Sorry but this mailbox is used only to administer the mailing"; $ err_sbj \u003d "error"; $ Headers \u003d "From: Subscribe Robot X-Mailer: PHP4 CONTENT-TYPE: text / plain; charset \u003d windows-1251"; if ($ n! \u003d 0) (WHILE ($ M ++< $n) { $h = imap_header($my_box, $m); $s = imap_fetch_overview($my_box, $m); $h = $h->fROM; Foreach ($ H As $ k \u003d\u003e $ V) ($ Mailbox \u003d $ V-\u003e Mailbox; $ Host \u003d $ V-\u003e Host; $ Personal \u003d $ V-\u003e Personal; $ email \u003d $ Mailbox. "@". $ host; $ my_email \u003d mysql_escape_string ($ email);) foreach ($ s AS $ k \u003d\u003e $ V) $ subj \u003d $ v-\u003e subject; if ($ subj \u003d\u003d "Subscribe") (mysql_query ("update table set stat \u003d 1 where email \u003d $ My_Email"); // print mysql_error (); $ del \u003d imap_delete ($ MY_BOX, $ M); mail ($ Email, $ add_sbj, $ add_text, $ Headers);) ELSE if ($ subj \u003d\u003d "unsubscribe") (mysql_query ("delete from table where email \u003d $ My_Email"); $ del \u003d imap_delete ($ My_box, $ M) ; Mail ($ email, $ del_sbj, $ del_text, $ Headers);) ELSE ($ del \u003d imap_delete ($ Open_Box, $ M); mail ($ email, $ er_sbj, $ er_text, $ headers);)) $ Clear \u003d imap_expunge ($ MY_BOX); )

In ListingE, there are no some details, such as possible converting from Win in KOI, rechecking the sender's mailbox, etc. These are already functional excesses that everyone can add as needed.