如何从此电子邮件中获取附件?
这封电子邮件是从一台苹果电脑发送的,电子邮件的结构与其他电子邮件结构不一样(惊喜)..这里配置的部分比其他部分更深。
该脚本适用于所有其他电子邮件,其中包含该文件的部分位于第一维,但不包含此部分
$part->dparameters[0]->value
会返回文件名,但strlen($data)
会返回0
$structure = imap_fetchstructure($this->stream, $this->msgno);
if(isset($structure->parts)){
print_r($structure->parts);
$this->parse_parts($structure->parts);
}
function parse_parts($parts){
foreach($parts as $section => $part){
if(isset($part->parts)){
// some mails have one extra dimension
$this->parse_parts($part->parts);
}
elseif(isset($part->disposition)){
if(in_array(strtolower($part->disposition), array('attachment','inline'))){
$data = imap_fetchbody($this->stream, $this->msgno, $section+1);
echo $part->dparameters[0]->value.' '.strlen($data)."\n";
}
}
}
}
Array
(
[0] => stdClass Object
(
[type] => 0
[encoding] => 0
[ifsubtype] => 1
[subtype] => PLAIN
[ifdescription] => 0
[ifid] => 0
[lines] => 15
[bytes] => 173
[ifdisposition] => 0
[ifdparameters] => 0
[ifparameters] => 1
[parameters] => Array
(
[0] => stdClass Object
(
[attribute] => CHARSET
[value] => us-ascii
)
)
)
[1] => stdClass Object
(
[type] => 1
[encoding] => 0
[ifsubtype] => 1
[subtype] => MIXED
[ifdescription] => 0
[ifid] => 0
[bytes] => 23420
[ifdisposition] => 0
[ifdparameters] => 0
[ifparameters] => 1
[parameters] => Array
(
[0] => stdClass Object
(
[attribute] => BOUNDARY
[value] => Apple-Mail=_800896E0-A9C9-456E-B063-79CED9DD4FD7
)
)
[parts] => Array
(
[0] => stdClass Object
(
[type] => 0
[encoding] => 0
[ifsubtype] => 1
[subtype] => HTML
[ifdescription] => 0
[ifid] => 0
[bytes] => 136
[ifdisposition] => 0
[ifdparameters] => 0
[ifparameters] => 1
[parameters] => Array
(
[0] => stdClass Object
(
[attribute] => CHARSET
[value] => us-ascii
)
)
)
[1] => stdClass Object
(
[type] => 3
[encoding] => 3
[ifsubtype] => 1
[subtype] => PDF
[ifdescription] => 0
[ifid] => 0
[bytes] => 17780
[ifdisposition] => 1
[disposition] => INLINE
[ifdparameters] => 1
[dparameters] => Array
(
[0] => stdClass Object
(
[attribute] => FILENAME
[value] => 057 - LPJ - Stik og labels.pdf
)
)
[ifparameters] => 1
[parameters] => Array
(
[0] => stdClass Object
(
[attribute] => NAME
[value] => 057 - LPJ - Stik og labels.pdf
)
)
)
[2] => stdClass Object
(
[type] => 0
[encoding] => 4
[ifsubtype] => 1
[subtype] => HTML
[ifdescription] => 0
[ifid] => 0
[lines] => 75
[bytes] => 4931
[ifdisposition] => 0
[ifdparameters] => 0
[ifparameters] => 1
[parameters] => Array
(
[0] => stdClass Object
(
[attribute] => CHARSET
[value] => us-ascii
)
)
)
)
)
)
答案 0 :(得分:13)
您没有为嵌套附件提供正确的部分编号。您需要在递归步骤中传入节号。
function parse_parts($parts, $parentsection = ""){
foreach($parts as $subsection => $part){
$section = $parentsection . ($subsection + 1);
if(isset($part->parts)){
// some mails have one extra dimension
$this->parse_parts($part->parts, $section . "." );
}
elseif(isset($part->disposition)){
if(in_array(strtolower($part->disposition), array('attachment','inline'))){
$data = imap_fetchbody($this->stream, $this->msgno, $section );
echo 'Getting section ' . $section;
echo $part->dparameters[0]->value.' '.strlen($data)."\n";
}
}
}
}
(未经测试,但应做正确的事......)
答案 1 :(得分:5)
下一个代码会显示INBOX中的目录和电子邮件
$mailbox = imap_open ("{correo.servidor.com:993/imap/ssl/novalidate-cert}INBOX", "correo@usuario.com", "PASSWORD");
if (!$mailbox){
die('murio');
}
echo "<h1>Buzones</h1>\n";
$carpetas = imap_listmailbox($mailbox, "{correo.patronato.unam.mx:993}", "*");
if ($carpetas == false) {
echo "Llamada fallida<br />\n";
} else {
foreach ($carpetas as $val) {
echo $val . "<br />\n";
}
}
echo "<h1>Cabeceras en INBOX</h1>\n";
$cabeceras = imap_headers($mailbox);
if ($cabeceras == false) {
echo "Llamada fallida<br />\n";
} else {
foreach ($cabeceras as $val) {
echo $val . "<br />\n";
}
}
$numMessages = imap_num_msg($mailbox);
for ($i = $numMessages; $i > 0; $i--) {
$header = imap_header($mailbox, $i);
$fromInfo = $header->from[0];
$replyInfo = $header->reply_to[0];
// print_r($header);
$details = array(
"fromAddr" => (isset($fromInfo->mailbox) && isset($fromInfo->host))
? $fromInfo->mailbox . "@" . $fromInfo->host : "",
"fromName" => (isset($fromInfo->personal))
? $fromInfo->personal : "",
"replyAddr" => (isset($replyInfo->mailbox) && isset($replyInfo->host))
? $replyInfo->mailbox . "@" . $replyInfo->host : "",
"replyName" => (isset($replyTo->personal))
? $replyto->personal : "",
"subject" => (isset($header->subject))
? $header->subject : "",
"udate" => (isset($header->udate))
? $header->udate : "",
"Unseen" => (isset($header->Unseen))
? $header->Unseen : "-"
);
$uid = imap_uid($mailbox, $i);
echo "<ul>";
echo "<li><strong>From:</strong>" . $details["fromName"];
echo " " . $details["fromAddr"] . "</li>";
echo "<li><strong>Subject:</strong> " . $details["subject"] . "</li>";
echo "<li><strong>Estatus:</strong> " . $details["Unseen"] . "</li>";
echo '<li><a href="test_imap_attachment.php?folder=' . $folder . '&uid=' . $i . '">Read</a></li>';
echo "</ul>";
}
imap_close($mailbox);
test_imap_attachment.php代码,显示附件文件
function getAttachments($imap, $mailNum, $part, $partNum) {
$attachments = array();
if (isset($part->parts)) {
foreach ($part->parts as $key => $subpart) {
if($partNum != "") {
$newPartNum = $partNum . "." . ($key + 1);
}
else {
$newPartNum = ($key+1);
}
$result = getAttachments($imap, $mailNum, $subpart,
$newPartNum);
if (count($result) != 0) {
array_push($attachments, $result);
}
}
}
else if (isset($part->disposition)) {
// print_r($part);
if (strtoupper($part->disposition) == "ATTACHMENT") {
$partStruct = imap_bodystruct($imap, $mailNum, $partNum);
$attachmentDetails = array(
"name" => $part->dparameters[0]->value,
"subtype" => $partStruct->subtype,
"partNum" => $partNum,
"enc" => $partStruct->encoding
);
return $attachmentDetails;
}
}
return $attachments;
}
$mailbox = imap_open ("{correo.servidor.com:993/imap/ssl/novalidate-cert}INBOX", "correo@usuario.com", "PASSWORD");
$uid = $_GET['uid'];
$mailStruct = imap_fetchstructure($mailbox, $uid);
$attachments = getAttachments($mailbox, $uid, $mailStruct, "");
echo "Attachments: ";
echo "<ul>";
foreach ($attachments as $attachment) {
echo '<li><a href="test_imap_download.php?func=' . $func . '&folder=' . $folder . '&uid=' . $uid .
'&part=' . $attachment["partNum"] . '&enc=' . $attachment["enc"] . '">' .
$attachment["name"] . "</a></li>";
}
echo "</ul>";
下一个代码将文件保存在同一台服务器上:test_imap_download.php
function downloadAttachment($imap, $uid) {
$structure = imap_fetchstructure($imap, $uid);
$attachments = '';
if(isset($structure->parts) && count($structure->parts)) {
for($i=0; $i<count($structure->parts); $i++) {
if(strtoupper($structure->parts[$i]->disposition) == 'ATTACHMENT') {
$attachments[$i] = array(
'is_attachment' => false,
'filename' => '',
'name' => '',
'attachment' => '');
if($structure->parts[$i]->ifdparameters) {
foreach($structure->parts[$i]->dparameters as $object) {
if(strtolower($object->attribute) == 'filename') {
$attachments[$i]['is_attachment'] = true;
$attachments[$i]['filename'] = $object->value;
}
}
}
if($structure->parts[$i]->ifparameters) {
foreach($structure->parts[$i]->parameters as $object) {
if(strtolower($object->attribute) == 'name') {
$attachments[$i]['is_attachment'] = true;
$attachments[$i]['name'] = $object->value;
}
}
}
if($attachments[$i]['is_attachment']) {
$attachments[$i]['attachment'] = imap_fetchbody($imap, $uid, $i+1);
if($structure->parts[$i]->encoding == 3) { // 3 = BASE64
$attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
}elseif($structure->parts[$i]->encoding == 4) { // 4 = QUOTED-PRINTABLE
$attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
}
}
file_put_contents('directorio/'.$attachments[$i]['filename'], $attachments[$i]['attachment']);
}
}
}
}
$mailbox = imap_open ("{correo.servidor.com:993/imap/ssl/novalidate-cert}INBOX", "correo@usuario.com", "PASSWORD");
$uid = $_GET["uid"];
$partNum = $_GET["partNum"];
downloadAttachment($mailbox, $uid);
我使用了此页面中的代码:
http://www.sitepoint.com/exploring-phps-imap-library-2/
Downloading attachments to directory with IMAP in PHP, randomly works
答案 2 :(得分:1)
我不是特别了解Mac电子邮件,但是这里有一些代码,我会通过每个部分来查看它是否是“附件”并将文件保存在某个地方以便稍后调用它。
$body = imap_fetchstructure($box, $i);
$attachments = '';
$att = count($body->parts);
if($att >=2) {
for($a=0;$a<$att;$a++) {
if($body->parts[$a]->disposition == 'ATTACHMENT') {
$file = imap_base64(imap_fetchbody($box, $i, $a+1));
$string = genRandomString();
if(!file_exists('/var/www/email_store/'.$_SESSION['site_user_id'])) {
mkdir('/var/www/email_store/'.$_SESSION['site_user_id'].'/');
}
$attachments .= $body->parts[$a]->dparameters[0]->value.'[#]'.$string.',';
file_put_contents('/var/www/email_store/'.$_SESSION['site_user_id'].'/'.$string,$file);
}
}
答案 3 :(得分:0)
我从这里的其他用户那里获取了代码,我为自己创建了此功能,该功能使我对电子邮件的结构有了一个完美的了解。该函数的结果如下所示:
.widget4 {
padding: 0;
background-color: #FED007;
}
.widget4-wrapper {
padding: 25px 25px 0 25px; /* change these values as you like */
background-color: #fff;
}
现在很容易遍历它并提取电子邮件的任何部分。 例如,如果我想要那个excel文件,则在这里获取节号“ 2”:
array (
0 =>
array (
'section_num' => '1.1',
'type' => 0,
'subtype' => 'PLAIN',
'size_bytes' => 128,
),
1 =>
array (
'section_num' => '1.2.1',
'type' => 0,
'subtype' => 'HTML',
'size_bytes' => 527,
),
2 =>
array (
'section_num' => '1.2.2',
'type' => 5,
'subtype' => 'GIF',
'disposition' => 'inline',
'size_bytes' => 3304,
'file_name' => 'logo_email.gif',
),
3 =>
array (
'section_num' => '2',
'type' => 3,
'subtype' => 'VND.OPENXMLFORMATS-OFFICEDOCUMENT.SPREADSHEETML.SHEET',
'disposition' => 'attachment',
'size_bytes' => 14742,
'file_name' => 'my_excel_table.xlsx',
),
)
最后是我的函数,它为我提供了很好的概述以及使用示例:
$excelData = imap_fetchbody($imapConnection, $msgNumber, '2')