Bonjour,

Je suis artisan et je bricole le php en amateur depuis quelques années. Pour joindre l'utile à l'agréable, j'ai fait un script (basé sur un que j'ai trouvé) qui me permet de récupérer les factures PDF de mes fournisseurs en pièce jointe depuis ma boite mail, puis de les parser.
Cela marche pour la quasi-totalité de mes factures à l'exception d'un fournisseur et cela m'embête bien.

Je précise que les mails de ce fournisseur sont générer automatiquement.

Lorsque je télécharge la pièce jointe manuellement depuis mon client de messagerie (Thunder birds), pas de problème le PDF peut être ouvert et parsé.

En revanche le PDF que je récupère depuis mon script est mauvais.


Voici les messages d'erreur que j'ai :

En affichant le PDF dans vsCode :

PDF.js v2.10.377 (identifiant de compilation : 156762c48)
Message : Invalid PDF structure.


En ouvrant le PDF avec Acrobat :

Nom : temps.jpg
Affichages : 209
Taille : 50,4 Ko

J'ai l'impression que cela viens du décodage

Voici le script :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<?php
$server = '{monserver}INBOX';
$username = 'mon@mail.com';
$password = 'pass';
 
$imap = imap_open($server, $username, $password) or die("imap connection error");
$message_count = imap_num_msg($imap);
 
for($m = $message_count; $m >= $message_count-5; $m--) //je regarde sur les 5 derniers mails
{
 
    $header = imap_headerinfo($imap, $m);
    $adresse_expediteur = iconv_mime_decode($header->fromaddress, 0, "ISO-8859-1");
    if(preg_match('/mail@de-mon-fournisseur.com/' ,$adresse_expediteur)) // je regarde si ça viens de mon fournisseur
    {
        //mise des différentes infos dans un tableau
        $email[$m]['from'] = $header->from[0]->mailbox.'@'.$header->from[0]->host;
        $email[$m]['fromaddress'] = $header->from[0]->personal;
        $email[$m]['to'] = $header->to[0]->mailbox;
        $email[$m]['subject'] = $header->subject;
        $email[$m]['message_id'] = $header->message_id;
        $email[$m]['date'] = $header->udate;
        $from = $email[$m]['fromaddress'];
        $from_email = $email[$m]['from'];
        $to = $email[$m]['to'];
        $subject = $email[$m]['subject'];
 
        $structure = imap_fetchstructure($imap, $m);
        $attachments = array();
 
        //Je recherche si il y a une pièce jointe
        if(isset($structure->parts) && count($structure->parts))
        {
            for($i = 0; $i < count($structure->parts); $i++)
            {
                echo $i;
                $attachments[$i] = array(   'is_attachment' => false,
                                            'filename' => '',
                                            'name' => '',
                                            'Dparameter' => '',
                                            'parameter' => '',
                                            'attachment' => '');
                if($structure->parts[$i]->ifdparameters)
                {
                    $attachments[$i]['encoding'] = $structure->parts[$i]->encoding;
                    foreach($structure->parts[$i]->dparameters as $object)
                    {
                        if(strtolower($object->attribute) == 'filename')
                        {
                            $attachments[$i]['is_attachment'] = true;
                            $attachments[$i]['filename'] = $object->value;
                            $attachments[$i]['Dparameter'] = "oui";
                        }
                    }
                }
                else
                {
                    if($structure->parts[$i]->parts)
                    {
                        foreach($structure->parts[$i]->parts as $key => $sous_array)
                        {
                            $attachments[$i]['encoding'] = $sous_array->encoding;
                            $attachments[$i]['key'] = $key;
                            if($sous_array->disposition == 'attachment')
                            {
                                if($sous_array->parameters[0]->attribute == 'name')
                                {
                                    $attachments[$i]['is_attachment'] = true;
                                    $attachments[$i]['name'] = $sous_array->parameters[0]->value;
                                    $attachments[$i]['filename'] = $sous_array->parameters[0]->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;
                            $attachments[$i]['parameter'] = "oui";
                        }
                    }
                }
                if($attachments[$i]['is_attachment'])
                {
                    $attachments[$i]['attachment'] = imap_fetchbody($imap, $m, $i+1, FT_PEEK);
 
                    //Je determine l'encodage
                    if($attachments[$i]['encoding'] == 3) // 3 = BASE64
                    { 
                        $attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
                    }
                    elseif($attachments[$i]['encoding'] == 4)// 4 = QUOTED-PRINTABLE
                    { 
                        $attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
                    }
                }
            }
        }
        foreach($attachments as $key => $attachment)
        {
            //Si c'est un PDF
            if(strstr(strtolower($attachment['name']), '.pdf'))
            {
                $name = $attachment['name'];
                $nom_d_origine = $name;
                $contents = $attachment['attachment'];
                $name = '../factures_fournisseurs/tmp/tmp_fact-'.$m.'.pdf';
                file_put_contents($fichier_final, $contents);
            }
        }
 
 
 
        // reste de mon script ou j'utilise le $fichier_final....
    }    
}
imap_expunge($imap);
imap_close($imap);
?>
Là je vous ai mis l'object résultant de imap_fetchstructure
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
stdClassObject
([type] => 1[encoding] => 0[ifsubtype] => 1[subtype] => MIXED
|¹[ifdescription] => 0[ifid] => 0[ifdisposition] => 0[ifdparameters] => 0[ifparameters] => 1[parameters] => Array
|	(
|	|²[0] => stdClassObject
|	|	(
|	|	|³[attribute] => boundary
|	|	|³[value] => --boundary_46_a865daa0-d325-478a-bc59-40c3330ba4d8
|	|	)
|	)[parts] => Array
|	(
|	|²[0] => stdClassObject
|	|	(
|	|	|³[type] => 1
|	|	|³[encoding] => 0
|	|	|³[ifsubtype] => 1
|	|	|³[subtype] => ALTERNATIVE
|	|	|³[ifdescription] => 0
|	|	|³[ifid] => 0
|	|	|³[ifdisposition] => 0
|	|	|³[ifdparameters] => 0
|	|	|³[ifparameters] => 1
|	|	|³[parameters] => Array
|	|	|	(
|	|	|	|⁴[0] => stdClassObject
|	|	|	|	(
|	|	|	|	|⁵[attribute] => boundary
|	|	|	|	|⁵[value] => --boundary_44_aaef25fe-1f85-4bb8-9df1-23ecceff9a7b
|	|	|	|	)
|	|	|	)
|	|	|³[parts] => Array
|	|	|	(
|	|	|	|⁴[0] => stdClassObject
|	|	|	|	(
|	|	|	|	|⁵[type] => 1
|	|	|	|	|⁵[encoding] => 0
|	|	|	|	|⁵[ifsubtype] => 1
|	|	|	|	|⁵[subtype] => RELATED
|	|	|	|	|⁵[ifdescription] => 0
|	|	|	|	|⁵[ifid] => 0
|	|	|	|	|⁵[ifdisposition] => 0
|	|	|	|	|⁵[ifdparameters] => 0
|	|	|	|	|⁵[ifparameters] => 1
|	|	|	|	|⁵[parameters] => Array
|	|	|	|	|	(
|	|	|	|	|	|⁶[0] => stdClassObject
|	|	|	|	|	|	(
|	|	|	|	|	|	|⁷[attribute] => boundary
|	|	|	|	|	|	|⁷[value] => --boundary_45_81e7fe2c-dc95-4446-b800-fd30f09702ac
|	|	|	|	|	|	)
|	|	|	|	|	|⁶[1] => stdClassObject
|	|	|	|	|	|	(
|	|	|	|	|	|	|⁷[attribute] => type
|	|	|	|	|	|	|⁷[value] => text/html
|	|	|	|	|	|	)
|	|	|	|	|	)
|	|	|	|	|⁵[parts] => Array
|	|	|	|	|	(
|	|	|	|	|	|⁶[0] => stdClassObject
|	|	|	|	|	|	(
|	|	|	|	|	|	|⁷[type] => 0
|	|	|	|	|	|	|⁷[encoding] => 3
|	|	|	|	|	|	|⁷[ifsubtype] => 1
|	|	|	|	|	|	|⁷[subtype] => HTML
|	|	|	|	|	|	|⁷[ifdescription] => 0
|	|	|	|	|	|	|⁷[ifid] => 0
|	|	|	|	|	|	|⁷[lines] => 11
|	|	|	|	|	|	|⁷[bytes] => 802
|	|	|	|	|	|	|⁷[ifdisposition] => 0
|	|	|	|	|	|	|⁷[ifdparameters] => 0
|	|	|	|	|	|	|⁷[ifparameters] => 1
|	|	|	|	|	|	|⁷[parameters] => Array
|	|	|	|	|	|	|	(
|	|	|	|	|	|	|	|⁸[0] => stdClassObject
|	|	|	|	|	|	|	|	(
|	|	|	|	|	|	|	|	|⁹[attribute] => charset
|	|	|	|	|	|	|	|	|⁹[value] => utf-8
|	|	|	|	|	|	|	|	)
|	|	|	|	|	|	|	)
|	|	|	|	|	|	)
|	|	|	|	|	|⁶[1] => stdClassObject
|	|	|	|	|	|	(
|	|	|	|	|	|	|⁷[type] => 5
|	|	|	|	|	|	|⁷[encoding] => 3
|	|	|	|	|	|	|⁷[ifsubtype] => 1
|	|	|	|	|	|	|⁷[subtype] => JPEG
|	|	|	|	|	|	|⁷[ifdescription] => 0
|	|	|	|	|	|	|⁷[ifid] => 1
|	|	|	|	|	|	|⁷[id] => 
|	|	|	|	|	|	|⁷[bytes] => 4940
|	|	|	|	|	|	|⁷[ifdisposition] => 0
|	|	|	|	|	|	|⁷[ifdparameters] => 0
|	|	|	|	|	|	|⁷[ifparameters] => 0
|	|	|	|	|	|	|⁷[parameters] => stdClassObject
|	|	|	|	|	|	|	(
|	|	|	|	|	|	|	)
|	|	|	|	|	|	)
|	|	|	|	|	)
|	|	|	|	)
|	|	|	)
|	|	)
|	|²[1] => stdClassObject
|	|	(
|	|	|³[type] => 1
|	|	|³[encoding] => 0
|	|	|³[ifsubtype] => 1
|	|	|³[subtype] => MIXED
|	|	|³[ifdescription] => 0
|	|	|³[ifid] => 0
|	|	|³[ifdisposition] => 0
|	|	|³[ifdparameters] => 0
|	|	|³[ifparameters] => 1
|	|	|³[parameters] => Array
|	|	|	(
|	|	|	|⁴[0] => stdClassObject
|	|	|	|	(
|	|	|	|	|⁵[attribute] => boundary
|	|	|	|	|⁵[value] => --boundary_47_c0a7e1bd-911b-4463-a672-59bf9b876d5d
|	|	|	|	)
|	|	|	)
|	|	|³[parts] => Array
|	|	|	(
|	|	|	|⁴[0] => stdClassObject
|	|	|	|	(
|	|	|	|	|⁵[type] => 3
|	|	|	|	|⁵[encoding] => 3
|	|	|	|	|⁵[ifsubtype] => 1
|	|	|	|	|⁵[subtype] => OCTET-STREAM
|	|	|	|	|⁵[ifdescription] => 0
|	|	|	|	|⁵[ifid] => 0
|	|	|	|	|⁵[bytes] => 508420
|	|	|	|	|⁵[ifdisposition] => 1
|	|	|	|	|⁵[disposition] => attachment
|	|	|	|	|⁵[ifdparameters] => 0
|	|	|	|	|⁵[ifparameters] => 1
|	|	|	|	|⁵[parameters] => Array
|	|	|	|	|	(
|	|	|	|	|	|⁶[0] => stdClassObject
|	|	|	|	|	|	(
|	|	|	|	|	|	|⁷[attribute] => name
|	|	|	|	|	|	|⁷[value] => Fact2704528_01-12-2024.pdf
|	|	|	|	|	|	)
|	|	|	|	|	)
|	|	|	|	)
|	|	|	)
|	|	)
|	)
)
Et ici le contenu de la variable $contents:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
----boundary_23_745a4124-1aae-4610-81f0-464a9c91ee93
Content-Type: application/octet-stream;
 name=Fact2704528_01-12-2024.pdf
Content-Disposition: attachment
Content-Transfer-Encoding: base64
 
JVBERi0xLjMNCjEgMCBvYmoNClsvUERGIC9UZXh0IC9JbWFnZUIgL0ltYWdlQyAvSW1hZ2VJXQ0K
 
[...]
 
byAxOSAwIFIg
Pj4NCnN0YXJ0eHJlZg0KMzc1NjI4DQolJUVPRg==
 
 
----boundary_23_745a4124-1aae-4610-81f0-464a9c91ee93--
Auriez vous une idée de la raison pour laquelle mon ficher est invalide ?

Je vous remercie