diff --git a/PST/10 ReadKulhavaPST.py b/PST/10 ReadKulhavaPST.py new file mode 100644 index 0000000..f997bd4 --- /dev/null +++ b/PST/10 ReadKulhavaPST.py @@ -0,0 +1,92 @@ +import win32com.client +import os + +# Your specific file path +pst_path = r'd:\Dropbox\!!!Days\Downloads Z230\PST\tkulhava.pst' + + +def main(): + if not os.path.exists(pst_path): + print(f"Error: File not found at {pst_path}") + return + + try: + # Connect to Outlook + outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI") + + # 1. Add the PST to Outlook (This makes it visible in the sidebar) + print(f"Mounting PST: {pst_path}...") + outlook.AddStore(pst_path) + + # 2. Find the folder object for this PST + # We search specifically for the folder that matches the filename 'tkulhava' + # or grab the last added store if the name doesn't match exactly. + pst_name = "tkulhava" # derived from filename usually + root_folder = None + + # Loop through all stores to find the new one + for folder in outlook.Folders: + if pst_name.lower() in folder.Name.lower(): + root_folder = folder + break + + # Fallback: Just grab the last folder in the list if name didn't match + if not root_folder: + root_folder = outlook.Folders.GetLast() + + print(f"Successfully opened root folder: {root_folder.Name}") + print("=" * 50) + + # 3. Start the recursive walk + print_subjects_recursively(root_folder) + + # 4. Cleanup: Remove the PST from Outlook + # (Comment this out if you want to keep it open in Outlook to inspect manually) + outlook.RemoveStore(root_folder) + print("\nDone. PST detached.") + + except Exception as e: + print(f"An error occurred: {e}") + + +def print_subjects_recursively(folder): + """ + Recursively prints subjects of emails in a folder and its subfolders. + """ + try: + # Print current folder name for context + # Check if folder has items + if folder.Items.Count > 0: + print(f"\n--- Folder: {folder.Name} ---") + + # Iterate through items + for item in folder.Items: + try: + # Class 43 is a standard MailItem. + # Other items (meeting requests, reports) might not have a Subject or behave differently. + if item.Class == 43: + print(f"Subject: {item.Subject}") + else: + # Attempt to print subject anyway (e.g., for Meeting Items) + print(f"[{type_name(item.Class)}] Subject: {item.Subject}") + except Exception: + # Skip items that are corrupted or unreadable + pass + + # Recursion: Go deeper into subfolders + for subfolder in folder.Folders: + print_subjects_recursively(subfolder) + + except Exception as e: + print(f"Skipping restricted folder '{folder.Name}': {e}") + + +def type_name(class_id): + # Helper to identify non-email items + if class_id == 53: return "Meeting" + if class_id == 46: return "Report" + return f"Type {class_id}" + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/PST/20 ReadKulhavaSavePhotos.py b/PST/20 ReadKulhavaSavePhotos.py new file mode 100644 index 0000000..6ca7fe2 --- /dev/null +++ b/PST/20 ReadKulhavaSavePhotos.py @@ -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() \ No newline at end of file