Examples
Basic Usage
Open and Inspect a PST File
package main
import (
"fmt"
"log"
outlookpst "github.com/grokify/outlook-pst-go"
)
func main() {
pst, err := outlookpst.Open("archive.pst")
if err != nil {
log.Fatal(err)
}
defer pst.Close()
fmt.Printf("Format: %s\n", pst.Format())
fmt.Printf("Encryption: %s\n", pst.CryptMethod())
name, _ := pst.Name()
fmt.Printf("Name: %s\n", name)
}
List All Folders
func listFolders(folder *outlookpst.Folder, indent string) {
name, _ := folder.Name()
count, _ := folder.ContentCount()
fmt.Printf("%s[%s] (%d items)\n", indent, name, count)
for subfolder, err := range folder.Subfolders() {
if err != nil {
continue
}
listFolders(subfolder, indent+" ")
}
}
func main() {
pst, _ := outlookpst.Open("archive.pst")
defer pst.Close()
root, _ := pst.RootFolder()
listFolders(root, "")
}
Read Messages from Inbox
func main() {
pst, _ := outlookpst.Open("archive.pst")
defer pst.Close()
inbox, err := pst.OpenFolder("Inbox")
if err != nil {
log.Fatal(err)
}
for msg, err := range inbox.Messages() {
if err != nil {
continue
}
subject, _ := msg.Subject()
sender, _ := msg.SenderName()
deliveryTime, _ := msg.DeliveryTime()
fmt.Printf("From: %s\n", sender)
fmt.Printf("Subject: %s\n", subject)
fmt.Printf("Date: %s\n", deliveryTime.Format("2006-01-02 15:04"))
fmt.Println("---")
}
}
Email Processing
Export Messages to Text Files
func exportMessages(folder *outlookpst.Folder, outputDir string) error {
os.MkdirAll(outputDir, 0755)
count := 0
for msg, err := range folder.Messages() {
if err != nil {
continue
}
subject, _ := msg.Subject()
body, _ := msg.Body()
sender, _ := msg.SenderName()
deliveryTime, _ := msg.DeliveryTime()
// Create filename from subject
filename := fmt.Sprintf("%04d_%s.txt", count,
sanitizeFilename(subject))
filepath := path.Join(outputDir, filename)
content := fmt.Sprintf("From: %s\nDate: %s\nSubject: %s\n\n%s",
sender, deliveryTime.Format(time.RFC1123), subject, body)
os.WriteFile(filepath, []byte(content), 0644)
count++
}
fmt.Printf("Exported %d messages to %s\n", count, outputDir)
return nil
}
Search Messages by Subject
func searchBySubject(folder *outlookpst.Folder, query string) []*outlookpst.Message {
var matches []*outlookpst.Message
query = strings.ToLower(query)
for msg, err := range folder.Messages() {
if err != nil {
continue
}
subject, _ := msg.Subject()
if strings.Contains(strings.ToLower(subject), query) {
matches = append(matches, msg)
}
}
return matches
}
Attachment Handling
func extractAttachments(folder *outlookpst.Folder, outputDir string) error {
os.MkdirAll(outputDir, 0755)
for msg, err := range folder.Messages() {
if err != nil {
continue
}
for att, err := range msg.Attachments() {
if err != nil {
continue
}
filename, _ := att.Filename()
if filename == "" {
continue
}
data, err := att.Data()
if err != nil {
log.Printf("Failed to read %s: %v", filename, err)
continue
}
// Handle duplicate filenames
outputPath := uniquePath(outputDir, filename)
os.WriteFile(outputPath, data, 0644)
size, _ := att.Size()
fmt.Printf("Extracted: %s (%d bytes)\n", filename, size)
}
}
return nil
}
Process Embedded Messages
func processEmbeddedMessages(msg *outlookpst.Message, depth int) {
indent := strings.Repeat(" ", depth)
subject, _ := msg.Subject()
fmt.Printf("%sMessage: %s\n", indent, subject)
for att, err := range msg.Attachments() {
if err != nil {
continue
}
isEmbedded, _ := att.IsEmbeddedMessage()
if isEmbedded {
embeddedMsg, err := att.OpenAsMessage()
if err != nil {
continue
}
// Recursively process
processEmbeddedMessages(embeddedMsg, depth+1)
}
}
}
Statistics
Generate Folder Statistics
type FolderStats struct {
Name string
MessageCount int
TotalSize int64
Subfolders int
}
func getFolderStats(folder *outlookpst.Folder) FolderStats {
name, _ := folder.Name()
count, _ := folder.MessageCount()
var totalSize int64
for msg, err := range folder.Messages() {
if err != nil {
continue
}
size, _ := msg.MessageSize()
totalSize += int64(size)
}
subfolderCount, _ := folder.SubfolderCount()
return FolderStats{
Name: name,
MessageCount: count,
TotalSize: totalSize,
Subfolders: subfolderCount,
}
}
Count Messages by Sender
func countBySender(folder *outlookpst.Folder) map[string]int {
counts := make(map[string]int)
for msg, err := range folder.Messages() {
if err != nil {
continue
}
sender, _ := msg.SenderEmail()
if sender == "" {
sender, _ = msg.SenderName()
}
if sender == "" {
sender = "(unknown)"
}
counts[sender]++
}
return counts
}
Export to JSON
type MessageJSON struct {
Subject string `json:"subject"`
Sender string `json:"sender"`
SenderEmail string `json:"sender_email"`
To string `json:"to"`
Date time.Time `json:"date"`
Body string `json:"body"`
}
func exportToJSON(folder *outlookpst.Folder, outputPath string) error {
var messages []MessageJSON
for msg, err := range folder.Messages() {
if err != nil {
continue
}
subject, _ := msg.Subject()
sender, _ := msg.SenderName()
senderEmail, _ := msg.SenderEmail()
to, _ := msg.DisplayTo()
deliveryTime, _ := msg.DeliveryTime()
body, _ := msg.Body()
messages = append(messages, MessageJSON{
Subject: subject,
Sender: sender,
SenderEmail: senderEmail,
To: to,
Date: deliveryTime,
Body: body,
})
}
data, err := json.MarshalIndent(messages, "", " ")
if err != nil {
return err
}
return os.WriteFile(outputPath, data, 0644)
}
Export to CSV
func exportToCSV(folder *outlookpst.Folder, outputPath string) error {
file, err := os.Create(outputPath)
if err != nil {
return err
}
defer file.Close()
writer := csv.NewWriter(file)
defer writer.Flush()
// Header
writer.Write([]string{"Subject", "From", "To", "Date", "Size"})
for msg, err := range folder.Messages() {
if err != nil {
continue
}
subject, _ := msg.Subject()
sender, _ := msg.SenderName()
to, _ := msg.DisplayTo()
deliveryTime, _ := msg.DeliveryTime()
size, _ := msg.MessageSize()
writer.Write([]string{
subject,
sender,
to,
deliveryTime.Format(time.RFC3339),
fmt.Sprintf("%d", size),
})
}
return nil
}
Creating PST Files
Create a New PST with Folders
package main
import (
"fmt"
"log"
outlookpst "github.com/grokify/outlook-pst-go"
"github.com/grokify/outlook-pst-go/pkg/disk"
)
func main() {
pst, err := outlookpst.Create("new-archive.pst", disk.FormatUnicode)
if err != nil {
log.Fatal(err)
}
defer pst.Close()
ctx, _ := pst.BeginWrite()
root, _ := pst.RootFolder()
// Create standard folder structure
folders := []string{"Inbox", "Sent Items", "Drafts", "Deleted Items", "Outbox"}
for _, name := range folders {
if _, err := ctx.CreateFolder(root, name); err != nil {
ctx.Rollback()
log.Fatalf("Failed to create %s: %v", name, err)
}
}
ctx.Commit()
fmt.Println("PST created with standard folders")
}
Create Messages with Attachments
func createMessageWithAttachments(pst *outlookpst.PST) error {
ctx, err := pst.BeginWrite()
if err != nil {
return err
}
inbox, _ := pst.OpenFolder("Inbox")
// Read attachment file
pdfData, err := os.ReadFile("report.pdf")
if err != nil {
ctx.Rollback()
return err
}
_, err = ctx.CreateMessage(inbox).
SetSubject("Q4 Report with Attachments").
SetBody("Please find the report attached.").
SetFrom("Finance", "finance@company.com").
AddTo("CEO", "ceo@company.com").
AddCC("CFO", "cfo@company.com").
SetSentTime(time.Now()).
AddAttachmentWithMime("Q4-Report.pdf", pdfData, "application/pdf").
Build()
if err != nil {
ctx.Rollback()
return err
}
return ctx.Commit()
}
Import Emails from Another Source
type EmailData struct {
Subject string
Body string
From string
FromEmail string
To []string
Date time.Time
}
func importEmails(pst *outlookpst.PST, emails []EmailData) error {
ctx, err := pst.BeginWrite()
if err != nil {
return err
}
root, _ := pst.RootFolder()
inbox, _ := outlookpst.GetOrCreateFolder(ctx, root, "Imported")
for _, email := range emails {
builder := ctx.CreateMessage(inbox).
SetSubject(email.Subject).
SetBody(email.Body).
SetFrom(email.From, email.FromEmail).
SetSentTime(email.Date)
for _, to := range email.To {
builder.AddTo("", to)
}
if _, err := builder.Build(); err != nil {
log.Printf("Failed to import '%s': %v", email.Subject, err)
}
}
return ctx.Commit()
}
Archive Old Messages
func archiveOldMessages(pst *outlookpst.PST, olderThan time.Time) error {
ctx, err := pst.BeginWrite()
if err != nil {
return err
}
root, _ := pst.RootFolder()
inbox, _ := root.FindSubfolder("Inbox")
archive, _ := outlookpst.GetOrCreateFolder(ctx, root, "Archive")
archived := 0
for msg, err := range inbox.Messages() {
if err != nil {
continue
}
sentTime, _ := msg.SubmitTime()
if sentTime.Before(olderThan) {
if err := outlookpst.MoveMessage(ctx, msg, archive); err == nil {
archived++
}
}
}
if err := ctx.Commit(); err != nil {
return err
}
fmt.Printf("Archived %d messages\n", archived)
return nil
}
Copy PST Contents
func copyPSTContents(srcPath, dstPath string) error {
// Open source
src, err := outlookpst.Open(srcPath)
if err != nil {
return fmt.Errorf("failed to open source: %w", err)
}
defer src.Close()
// Create destination
dst, err := outlookpst.Create(dstPath, src.Format())
if err != nil {
return fmt.Errorf("failed to create destination: %w", err)
}
defer dst.Close()
ctx, _ := dst.BeginWrite()
srcRoot, _ := src.RootFolder()
dstRoot, _ := dst.RootFolder()
// Copy recursively
copyFolder(ctx, srcRoot, dstRoot)
return ctx.Commit()
}
func copyFolder(ctx *outlookpst.WriteContext, src, dst *outlookpst.Folder) {
// Copy messages
for msg, err := range src.Messages() {
if err != nil {
continue
}
subject, _ := msg.Subject()
body, _ := msg.Body()
sentTime, _ := msg.SubmitTime()
ctx.CreateMessage(dst).
SetSubject(subject).
SetBody(body).
SetSentTime(sentTime).
Build()
}
// Copy subfolders
for subfolder, err := range src.Subfolders() {
if err != nil {
continue
}
name, _ := subfolder.Name()
newFolder, err := ctx.CreateFolder(dst, name)
if err != nil {
continue
}
copyFolder(ctx, subfolder, newFolder)
}
}
Compact a PST File
func compactPST(inputPath, outputPath string) error {
return outlookpst.Compact(inputPath, outputPath, outlookpst.CompactOptions{
RemoveDeletedItems: true,
DefragmentBlocks: true,
})
}
Bulk Delete Old Messages
func deleteOldMessages(pst *outlookpst.PST, folder *outlookpst.Folder, olderThan time.Time) (int, error) {
ctx, err := pst.BeginWrite()
if err != nil {
return 0, err
}
deleted := 0
var toDelete []*outlookpst.Message
// Collect messages to delete (can't delete while iterating)
for msg, err := range folder.Messages() {
if err != nil {
continue
}
sentTime, _ := msg.SubmitTime()
if sentTime.Before(olderThan) {
toDelete = append(toDelete, msg)
}
}
// Delete collected messages
for _, msg := range toDelete {
if err := ctx.DeleteMessage(msg); err == nil {
deleted++
}
}
if err := ctx.Commit(); err != nil {
return 0, err
}
return deleted, nil
}