Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] 关于首页文档中,getMailboxes()方法,邮箱里中文文件夹会返回乱码的一些疑问 #339

Closed
mostanily opened this issue May 31, 2019 · 6 comments
Labels
needs investigation This will be tested / debugged or checked out. phpunit Adding or updating PHPUnit tests for this issue.

Comments

@mostanily
Copy link

先说说我遇到的问题

我想获取邮箱中其他文件夹下的邮件,然后我找到了你在首页说明文档的例子,就是这个:


    $folders = $mailbox->getMailboxes('*');
    foreach($folders as $folder) {  
    
        // switch to particular mailbox 
        $mailbox->switchMailbox($folder['fullpath']);   
                
        // search in particular mailbox 
        $mails_ids[$folder['fullpath']] = $mailbox->searchMailbox('SINCE "20190501"');   
    }
    dd($mails_ids);

然后我调试的时候,发现在这个返回的结果中,邮箱里面带中文名称的文件夹中文部分全部都显示乱码,类似这样的 {xxxxxxxxx:993/imap/ssl/novalidate-cert}Jira&kBp35Q-" => [],如果是英文名称就没有问题。
后来查了下源码,发现其中关于名称解析这一部分,没有进行转码,大致像下面这样


        public function getMailboxes($search = "*") {
		$arr = [];
		if($t = imap_getmailboxes($this->getImapStream(), $this->imapPath, $search)) {
			foreach($t as $item) {
                                //这句是我加的
				$name = $this->decodeStringFromUtf7ImapToUtf8($item->name);
				//$name = $item->name;
				$arr[] = [
					"fullpath" => $name,
					"attributes" => $item->attributes,
					"delimiter" => $item->delimiter,
					"shortpath" => substr($name, strpos($name, '}') + 1),
				];
			}
		}
		return $arr;
	}

我加了这个decodeStringFromUtf7ImapToUtf8()这个转码方法后,获取的内容就展示正常了,类似这样: "{xxxxxxxxx:993/imap/ssl/novalidate-cert}Jira通知" => array:24 [▶]

之后又看到了这个方法getListingFolders(),这个方法里面是做了decodeStringFromUtf7ImapToUtf8()转码操作的;通过这个方法获取的邮箱文件夹列表中文名称是显示正常的。

有点疑问,就是getMailboxes这个方法为啥没有进行转码操作?

@mostanily mostanily added the needs investigation This will be tested / debugged or checked out. label May 31, 2019
@Sebbo94BY Sebbo94BY added the phpunit Adding or updating PHPUnit tests for this issue. label May 31, 2019
@Sebbo94BY
Copy link
Collaborator

I've changed / fixed this as suggested by you. See above referenced commit.

It seems to work with any kind of characters.

This change will be included in the next release.

@alukaa
Copy link

alukaa commented Sep 26, 2022

also one bug here, i try to get the folders of QQ domain email. i used $mailBox->getMailboxes('*') get rong response
image
the reason is the floder name is ASCII encode, not utf7. so should be like this
image

@alukaa
Copy link

alukaa commented Sep 26, 2022

and the result is ok
image

@sn01615
Copy link

sn01615 commented Feb 7, 2023

QQ邮箱解码有问题

$out = imap_utf7_decode($str);

修改:
https:/sn01615/php-imap/blob/72fbe1617d0bd7b3acdae241f7ac0aeebfc79c07/src/PhpImap/Mailbox.php#L1968

@michalcharvat
Copy link

None of these solutions mentioned above solved this issue. Folders encoding is ASCII for all folders and detect encoding or any other mentioned operation does not return localized gmail folder name. So I have went through Group Office I use as main project and the custom decoder works like a charm.

public static function utf7_decode(string $str)
{
    $Index_64 = array(
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, 63, -1, -1, -1,
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
        -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
        -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
    );

    $u7len = strlen($str);
    $str = strval($str);
    $p = $err = '';

    for ($i = 0; $u7len > 0; $i++, $u7len--) {
        $u7 = $str[$i];
        if ($u7 === '&') {
            $i++;
            $u7len--;
            $u7 = isset($str[$i]) ? $str[$i] : '';

            if ($u7len && $u7 == '-') {
                $p .= '&';
                continue;
            }

            $ch = 0;
            $k = 10;
            for (; $u7len > 0; $i++, $u7len--) {
                $u7 = $str[$i];

                if ((ord($u7) & 0x80) || ($b = $Index_64[ord($u7)]) == -1) {
                    break;
                }

                if ($k > 0) {
                    $ch |= $b << $k;
                    $k -= 6;
                } else {
                    $ch |= $b >> (-$k);
                    if ($ch < 0x80) {
                        /* Printable US-ASCII */
                        if (0x20 <= $ch && $ch < 0x7f) {
                            return $err;
                        }
                        $p .= chr($ch);
                    } else if ($ch < 0x800) {
                        $p .= chr(0xc0 | ($ch >> 6));
                        $p .= chr(0x80 | ($ch & 0x3f));
                    } else {
                        $p .= chr(0xe0 | ($ch >> 12));
                        $p .= chr(0x80 | (($ch >> 6) & 0x3f));
                        $p .= chr(0x80 | ($ch & 0x3f));
                    }

                    $ch = ($b << (16 + $k)) & 0xffff;
                    $k += 10;
                }
            }

            /* Non-zero or too many extra bits */
            if ($ch || $k < 6) {
                return $err;
            }

            /* BASE64 not properly terminated */
            if (!$u7len || $u7 != '-') {
                return $err;
            }

            /* Adjacent BASE64 sections */
            if ($u7len > 2 && $str[$i + 1] === '&' && $str[$i + 2] != '-') {
                return $err;
            }
        } else if (ord($u7) < 0x20 || ord($u7) >= 0x7f) {
            /* Not printable US-ASCII */
            return $err;
        } else {
            $p .= $u7;
        }
    }

    return str_replace(array('\\\\', '\"'), array('\\', '"'), $p);
}

@Sebbo94BY
Copy link
Collaborator

@michalcharvat I would appreciate, if you could open a pull request with this change / fix. :)

michalcharvat added a commit to michalcharvat/php-imap that referenced this issue Mar 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs investigation This will be tested / debugged or checked out. phpunit Adding or updating PHPUnit tests for this issue.
Projects
None yet
Development

No branches or pull requests

5 participants