mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	add prototype archive pdf
This commit is contained in:
		
							
								
								
									
										46
									
								
								src/paperless_mail/mail_template/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/paperless_mail/mail_template/index.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | <!doctype html> | ||||||
|  | <html> | ||||||
|  |  | ||||||
|  | <head> | ||||||
|  |   <meta charset="UTF-8"> | ||||||
|  |   <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||||
|  |   <link href="output.css" rel="stylesheet"> | ||||||
|  | </head> | ||||||
|  |  | ||||||
|  | <body class="bg-white w-screen flex flex-col items-center"> | ||||||
|  |   <div class="container max-w-4xl"> | ||||||
|  |     <!-- Header --> | ||||||
|  |     <div class="grid grid-rows-5 grid-cols-12 gap-x-2 bg-slate-200 p-4"> | ||||||
|  |  | ||||||
|  |       <div class="col-start-11 col-span-2 row-start-1 text-right">23.04.2022 18:18</div> | ||||||
|  |  | ||||||
|  |       <div class="col-start-1 row-start-1 text-slate-400 text-right">From</div> | ||||||
|  |       <div class="col-start-2 col-span-8 row-start 1">{{ from }}</div> | ||||||
|  |  | ||||||
|  |       <div class="col-start-1 row-start-2 text-slate-400 text-right">Subject</div> | ||||||
|  |       <div class=" col-start-2 col-span-10 row-start 2 font-bold">{{ Subject }} | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <div class="col-start-1 row-start-3 text-slate-400 text-right">To</div> | ||||||
|  |       <div class="col-start-2 col-span-10 row-start 3">{{ To }} | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <div class="col-start-1 row-start-4 text-slate-400 text-right">CC</div> | ||||||
|  |       <div class="col-start-2 col-span-10 row-start 4">{{ CC }} | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       <div class="col-start-1 row-start-5 text-slate-400 text-right">BCC</div> | ||||||
|  |       <div class="col-start-2 col-span-10 row-start 5">{{ BCC }} | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <!-- Separator--> | ||||||
|  |     <div class="border-t border-solid border-b w-full h-[1px] box-content border-black mb-5 bg-slate-200"></div> | ||||||
|  |  | ||||||
|  |     <!-- Content--> | ||||||
|  |     <div class="w-full whitespace-pre-line">{{ content }} | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  | </body> | ||||||
|  |  | ||||||
|  | </html> | ||||||
							
								
								
									
										0
									
								
								src/paperless_mail/mail_template/output.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/paperless_mail/mail_template/output.css
									
									
									
									
									
										Normal file
									
								
							| @@ -8,9 +8,6 @@ from django.conf import settings | |||||||
| from documents.parsers import DocumentParser | from documents.parsers import DocumentParser | ||||||
| from documents.parsers import make_thumbnail_from_pdf | from documents.parsers import make_thumbnail_from_pdf | ||||||
| from documents.parsers import ParseError | from documents.parsers import ParseError | ||||||
| from PIL import Image |  | ||||||
| from PIL import ImageDraw |  | ||||||
| from PIL import ImageFont |  | ||||||
| from tika import parser | from tika import parser | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -112,22 +109,19 @@ class TikaDocumentParserEml(DocumentParser): | |||||||
|     logging_name = "paperless.parsing.tikaeml" |     logging_name = "paperless.parsing.tikaeml" | ||||||
|  |  | ||||||
|     def get_thumbnail(self, document_path, mime_type, file_name=None): |     def get_thumbnail(self, document_path, mime_type, file_name=None): | ||||||
|  |         if not self.archive_path: | ||||||
|  |             self.archive_path = self.generate_pdf(document_path) | ||||||
|  |  | ||||||
|         img = Image.new("RGB", (500, 700), color="white") |         return make_thumbnail_from_pdf( | ||||||
|         draw = ImageDraw.Draw(img) |             self.archive_path, | ||||||
|         font = ImageFont.truetype( |             self.tempdir, | ||||||
|             font=settings.THUMBNAIL_FONT_NAME, |             self.logging_group, | ||||||
|             size=20, |  | ||||||
|             layout_engine=ImageFont.LAYOUT_BASIC, |  | ||||||
|         ) |         ) | ||||||
|         draw.text((5, 5), self.text, font=font, fill="black") |  | ||||||
|  |  | ||||||
|         out_path = os.path.join(self.tempdir, "thumb.png") |  | ||||||
|         img.save(out_path) |  | ||||||
|  |  | ||||||
|         return out_path |  | ||||||
|  |  | ||||||
|     def extract_metadata(self, document_path, mime_type): |     def extract_metadata(self, document_path, mime_type): | ||||||
|  |         result = [] | ||||||
|  |         prefix_pattern = re.compile(r"(.*):(.*)") | ||||||
|  |  | ||||||
|         tika_server = settings.PAPERLESS_TIKA_ENDPOINT |         tika_server = settings.PAPERLESS_TIKA_ENDPOINT | ||||||
|         try: |         try: | ||||||
|             parsed = parser.from_file(document_path, tika_server) |             parsed = parser.from_file(document_path, tika_server) | ||||||
| @@ -136,17 +130,38 @@ class TikaDocumentParserEml(DocumentParser): | |||||||
|                 "warning", |                 "warning", | ||||||
|                 f"Error while fetching document metadata for " f"{document_path}: {e}", |                 f"Error while fetching document metadata for " f"{document_path}: {e}", | ||||||
|             ) |             ) | ||||||
|             return [] |             return result | ||||||
|  |  | ||||||
|         return [ |         for key, value in parsed["metadata"].items(): | ||||||
|             { |             if isinstance(value, list): | ||||||
|                 "namespace": "", |                 value = ", ".join([str(e) for e in value]) | ||||||
|                 "prefix": "", |             value = str(value) | ||||||
|                 "key": key, |             try: | ||||||
|                 "value": parsed["metadata"][key], |                 m = prefix_pattern.match(key) | ||||||
|             } |                 result.append( | ||||||
|             for key in parsed["metadata"] |                     { | ||||||
|         ] |                         "namespace": "", | ||||||
|  |                         "prefix": m.group(1), | ||||||
|  |                         "key": m.group(2), | ||||||
|  |                         "value": value, | ||||||
|  |                     }, | ||||||
|  |                 ) | ||||||
|  |             except AttributeError: | ||||||
|  |                 result.append( | ||||||
|  |                     { | ||||||
|  |                         "namespace": "", | ||||||
|  |                         "prefix": "", | ||||||
|  |                         "key": key, | ||||||
|  |                         "value": value, | ||||||
|  |                     }, | ||||||
|  |                 ) | ||||||
|  |             except Exception as e: | ||||||
|  |                 self.log( | ||||||
|  |                     "warning", | ||||||
|  |                     f"Error while reading metadata {key}: {value}. Error: " f"{e}", | ||||||
|  |                 ) | ||||||
|  |             result.sort(key=lambda item: (item["prefix"], item["key"])) | ||||||
|  |         return result | ||||||
|  |  | ||||||
|     def parse(self, document_path, mime_type, file_name=None): |     def parse(self, document_path, mime_type, file_name=None): | ||||||
|         self.log("info", f"Sending {document_path} to Tika server") |         self.log("info", f"Sending {document_path} to Tika server") | ||||||
| @@ -160,57 +175,94 @@ class TikaDocumentParserEml(DocumentParser): | |||||||
|                 f"{tika_server}: {err}", |                 f"{tika_server}: {err}", | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         text = re.sub(" +", " ", str(parsed)) |         metadata = parsed["metadata"].copy() | ||||||
|         text = re.sub("\n+", "\n", text) |  | ||||||
|         self.text = text |  | ||||||
|  |  | ||||||
|         print(text) |         subject = metadata.pop("dc:subject", "<no subject>") | ||||||
|  |         content = parsed["content"].strip() | ||||||
|  |  | ||||||
|  |         if content.startswith(subject): | ||||||
|  |             content = content[len(subject) :].strip() | ||||||
|  |  | ||||||
|  |         content = re.sub(" +", " ", content) | ||||||
|  |         content = re.sub("\n+", "\n", content) | ||||||
|  |  | ||||||
|  |         self.text = ( | ||||||
|  |             f"{content}\n" | ||||||
|  |             f"______________________\n" | ||||||
|  |             f"From: {metadata.pop('Message-From', '')}\n" | ||||||
|  |             f"To: {metadata.pop('Message-To', '')}\n" | ||||||
|  |             f"CC: {metadata.pop('Message-CC', '')}" | ||||||
|  |         ) | ||||||
|  |  | ||||||
|         try: |         try: | ||||||
|             self.date = dateutil.parser.isoparse(parsed["metadata"]["Creation-Date"]) |             self.date = dateutil.parser.isoparse(parsed["metadata"]["dcterms:created"]) | ||||||
|         except Exception as e: |         except Exception as e: | ||||||
|             self.log( |             self.log( | ||||||
|                 "warning", |                 "warning", | ||||||
|                 f"Unable to extract date for document " f"{document_path}: {e}", |                 f"Unable to extract date for document " f"{document_path}: {e}", | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         md_path = self.convert_to_md(document_path, file_name) |         self.archive_path = self.generate_pdf(document_path, parsed) | ||||||
|         self.archive_path = self.convert_md_to_pdf(md_path) |  | ||||||
|  |     def generate_pdf(self, document_path, parsed=None): | ||||||
|  |         if not parsed: | ||||||
|  |             self.log("info", f"Sending {document_path} to Tika server") | ||||||
|  |             tika_server = settings.PAPERLESS_TIKA_ENDPOINT | ||||||
|  |  | ||||||
|  |             try: | ||||||
|  |                 parsed = parser.from_file(document_path, tika_server) | ||||||
|  |             except Exception as err: | ||||||
|  |                 raise ParseError( | ||||||
|  |                     f"Could not parse {document_path} with tika server at " | ||||||
|  |                     f"{tika_server}: {err}", | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|  |         def clean_html(text: str): | ||||||
|  |             if isinstance(text, list): | ||||||
|  |                 text = ", ".join([str(e) for e in text]) | ||||||
|  |             if type(text) != str: | ||||||
|  |                 text = str(text) | ||||||
|  |             text = text.replace("&", "&") | ||||||
|  |             text = text.replace("<", "<") | ||||||
|  |             text = text.replace(">", ">") | ||||||
|  |             text = text.replace(" ", " ") | ||||||
|  |             text = text.replace("'", "'") | ||||||
|  |             text = text.replace('"', """) | ||||||
|  |             return text | ||||||
|  |  | ||||||
|     def convert_md_to_pdf(self, md_path): |  | ||||||
|         pdf_path = os.path.join(self.tempdir, "convert.pdf") |         pdf_path = os.path.join(self.tempdir, "convert.pdf") | ||||||
|         gotenberg_server = settings.PAPERLESS_TIKA_GOTENBERG_ENDPOINT |         gotenberg_server = settings.PAPERLESS_TIKA_GOTENBERG_ENDPOINT | ||||||
|         url = gotenberg_server + "/forms/chromium/convert/markdown" |         url = gotenberg_server + "/forms/chromium/convert/html" | ||||||
|  |  | ||||||
|  |         self.log("info", f"Converting {document_path} to PDF as {pdf_path}") | ||||||
|  |  | ||||||
|  |         subject = parsed["metadata"].pop("dc:subject", "<no subject>") | ||||||
|  |         content = parsed.pop("content", "<no content>").strip() | ||||||
|  |  | ||||||
|  |         if content.startswith(subject): | ||||||
|  |             content = content[len(subject) :].strip() | ||||||
|  |  | ||||||
|         self.log("info", f"Converting {md_path} to PDF as {pdf_path}") |  | ||||||
|         html = StringIO( |         html = StringIO( | ||||||
|             """ |             f""" | ||||||
| <!doctype html> |             <!doctype html> | ||||||
| <html lang="en"> |             <html lang="en"> | ||||||
|   <head> |               <head> | ||||||
|     <meta charset="utf-8"> |                 <meta charset="utf-8"> | ||||||
|     <title>My PDF</title> |                 <title>My PDF</title> | ||||||
|   </head> |               </head> | ||||||
|   <body> |               <body> | ||||||
|     {{ toHTML "convert.md" }} |                 <h1>{clean_html(subject)}</h1> | ||||||
|   </body> |                 <p>From: {clean_html(parsed['metadata'].pop('Message-From', ''))} | ||||||
| </html> |                 <p>To: {clean_html(parsed['metadata'].pop('Message-To', ''))} | ||||||
|         """, |                 <p>CC: {clean_html(parsed['metadata'].pop('Message-CC', ''))} | ||||||
|         ) |                 <p>Date: {clean_html(parsed['metadata'].pop('dcterms:created', ''))} | ||||||
|         md = StringIO( |                 <pre>{clean_html(content)}</pre> | ||||||
|             """ |               </body> | ||||||
| # Subject |             </html> | ||||||
|  |             """, | ||||||
| blub  \nblah |  | ||||||
| blib |  | ||||||
|         """, |  | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         files = { |         files = { | ||||||
|             "md": ( |  | ||||||
|                 os.path.basename(md_path), |  | ||||||
|                 md, |  | ||||||
|             ), |  | ||||||
|             "html": ( |             "html": ( | ||||||
|                 "index.html", |                 "index.html", | ||||||
|                 html, |                 html, | ||||||
| @@ -229,19 +281,3 @@ blib | |||||||
|             file.close() |             file.close() | ||||||
|  |  | ||||||
|         return pdf_path |         return pdf_path | ||||||
|  |  | ||||||
|     def convert_to_md(self, document_path, file_name): |  | ||||||
|         md_path = os.path.join(self.tempdir, "convert.md") |  | ||||||
|  |  | ||||||
|         self.log("info", f"Converting {document_path} to markdown as {md_path}") |  | ||||||
|  |  | ||||||
|         with open(md_path, "w") as file: |  | ||||||
|             md = [ |  | ||||||
|                 "# Subject", |  | ||||||
|                 "\n\n", |  | ||||||
|                 "blah", |  | ||||||
|             ] |  | ||||||
|             file.writelines(md) |  | ||||||
|             file.close() |  | ||||||
|  |  | ||||||
|         return md_path |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 phail
					phail