tw22
This commit is contained in:
142
PST/20 ReadKulhavaSavePhotos.py
Normal file
142
PST/20 ReadKulhavaSavePhotos.py
Normal file
@@ -0,0 +1,142 @@
|
||||
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()
|
||||
Reference in New Issue
Block a user