Files
walkfiles/PST/20 ReadKulhavaSavePhotos.py
2026-01-11 21:13:38 +01:00

142 lines
4.3 KiB
Python

import win32com.client
import os
import pathlib
# --- CONFIGURATION ---
pst_path = r'd:\Dropbox\!!!Days\Downloads Z230\PST\tkulhava.pst'
output_dir = r'd:\Dropbox\!!!Days\Downloads Z230\PST\pictures'
# Image extensions to look for (case insensitive)
IMAGE_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tif', '.tiff'}
def fix_encoding(text):
"""Repairs text wrongly decoded as cp1252 instead of cp1250."""
if not text: return ""
try:
return text.encode('cp1252').decode('cp1250')
except Exception:
return text
def get_unique_filepath(directory, filename):
"""
Checks if a file exists. If so, adds a counter (_1, _2) to the filename
until a unique name is found.
"""
# Clean filename of illegal characters just in case
filename = "".join(x for x in filename if x.isalnum() or x in "._- ")
path = pathlib.Path(directory) / filename
if not path.exists():
return path
# Split name and extension
stem = path.stem
suffix = path.suffix
counter = 1
while True:
new_filename = f"{stem}_{counter}{suffix}"
new_path = pathlib.Path(directory) / new_filename
if not new_path.exists():
return new_path
counter += 1
def process_item_attachments(item, save_folder):
"""Checks an item for attachments and saves pictures."""
try:
# Check if item has attachments
if item.Attachments.Count > 0:
for attachment in item.Attachments:
try:
# Get filename and extension
fname = getattr(attachment, 'FileName', '')
if not fname: continue
# Fix encoding on filename if needed (sometimes attachments inherit bad encoding)
fname = fix_encoding(fname)
ext = os.path.splitext(fname)[1].lower()
if ext in IMAGE_EXTENSIONS:
# Determine unique path
save_path = get_unique_filepath(save_folder, fname)
# Save the file
attachment.SaveAsFile(str(save_path))
print(f" [SAVED] {save_path.name}")
except Exception as e:
print(f" [ERROR saving attachment]: {e}")
except Exception:
# Some items (like corrupted notes) fail when accessing .Attachments
pass
def scan_folder_recursively(folder, save_folder):
"""Recursively walks folders and processes items."""
try:
folder_name = fix_encoding(folder.Name)
# Optional: Print folder progress
if folder.Items.Count > 0:
print(f"Scanning Folder: {folder_name}...")
# Process items in this folder
for item in folder.Items:
process_item_attachments(item, save_folder)
# Recursion
for subfolder in folder.Folders:
scan_folder_recursively(subfolder, save_folder)
except Exception as e:
print(f"Skipping folder '{fix_encoding(folder.Name)}': {e}")
def main():
# 1. Ensure output directory exists
if not os.path.exists(output_dir):
os.makedirs(output_dir)
print(f"Created directory: {output_dir}")
if not os.path.exists(pst_path):
print(f"Error: PST file not found at {pst_path}")
return
try:
# 2. Connect to Outlook
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
print(f"Mounting PST: {pst_path}...")
outlook.AddStore(pst_path)
# 3. Find the PST folder
pst_name = "tkulhava" # Usually derived from filename
root_folder = None
for folder in outlook.Folders:
if pst_name.lower() in folder.Name.lower():
root_folder = folder
break
if not root_folder:
root_folder = outlook.Folders.GetLast()
print(f"Opened: {fix_encoding(root_folder.Name)}")
print(f"Saving pictures to: {output_dir}")
print("=" * 50)
# 4. Start processing
scan_folder_recursively(root_folder, output_dir)
# 5. Cleanup
outlook.RemoveStore(root_folder)
print("\nDone. PST detached.")
except Exception as e:
print(f"Critical Error: {e}")
if __name__ == "__main__":
main()