CSC409 Advanced Java Programming

Advanced Java ProgrammingUnit 914 min read

Java Mail API & File Handling: Sending Emails & Processing Files

Unit 9 of Advanced Java Programming covers Java’s built-in email API for sending/receiving emails programmatically, and advanced file I/O (reading, writing, searching, and parsing files) with practical examples like log analysis, data extraction, and email automation. Learn to handle attachments, MIME types, and file f

TAKEAWAYS:

  • Java Mail API lets you send/receive emails programmatically using SMTP/IMAP protocols, with support for HTML emails, attachments, and authentication.
  • File Handling in Java includes reading/writing text/binary files, searching patterns (regex), and parsing structured data (CSV, JSON) using BufferedReader, FileWriter, and Scanner.
  • Email Structure: MIME types (e.g., text/plain, multipart/mixed) define how email content (text, HTML, attachments) is encoded and transmitted.
  • File Operations: Methods like Files.readAllLines(), Files.write(), and Path (NIO.2) simplify file handling compared to legacy File/FileInputStream.
  • Error Handling: Always wrap file/email operations in try-catch blocks to handle IOException, MessagingException, or AuthenticationFailedException.
  • Real-World Use: Automate email notifications (e.g., order confirmations in Daraz), parse log files (e.g., NTC server logs), or generate reports from CSV data (e.g., NEPSE stock analysis).

1. Java Mail API: Sending Emails Programmatically

The JavaMail API (part of the javax.mail package) enables Java programs to send, receive, and parse emails using standard protocols like SMTP (sending) and IMAP/POP3 (receiving). It abstracts low-level email protocols into high-level objects like Session, Message, and Transport.

0[object Object][object Object]1[object Object]2[object Object]3—
Email headers as a hash table (simplified MIME structure)
Authenticate + SendMIME-encoded dataDeliverSMTP ServerEmail Sender (JavaMail)Recipient ServerRecipient
Email transmission flow via SMTP (Gmail example)

Key Components

classDiagram
    class Session {
        +Properties getProperties()
        +Transport getTransport()
    }
    class Message {
        +void setFrom(Address)
        +void setRecipients(Message.RecipientType, Address[])
        +void setSubject(String)
        +void setContent(Object, String)
    }
    class Transport {
        +void send(Message)
        +void close()
    }
    Session --> Message : creates
    Message --> Transport : uses to send

How It Works

  1. Configure a Session with SMTP server details (host, port, credentials).
  2. Create a Message object, setting sender, recipients, subject, and content (text/HTML).
  3. Attach files (if needed) using MimeBodyPart and Multipart.
  4. Send via Transport.send().

Example: Sending an Email with Attachment

import javax.mail.*;
import javax.mail.internet.*;
import java.util.Properties;

public class EmailSender {
    public static void main(String[] args) {
        // 1. Set SMTP properties (e.g., Gmail)
        Properties props = new Properties();
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.smtp.port", "587");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");

        // 2. Create session with credentials
        Session session = Session.getInstance(props, new Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("your_email@gmail.com", "your_password");
            }
        });

        try {
            // 3. Create message
            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress("your_email@gmail.com"));
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("recipient@example.com"));
            message.setSubject("Test Email with Attachment");

            // 4. Add text and HTML parts
            MimeBodyPart textPart = new MimeBodyPart();
            textPart.setText("Hello, this is a test email.");

            MimeBodyPart htmlPart = new MimeBodyPart();
            htmlPart.setContent("<h1>HTML Content</h1><p>This is <b>bold</b>.</p>", "text/html");

            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(textPart);
            multipart.addBodyPart(htmlPart);

            // 5. Attach a file
            MimeBodyPart attachmentPart = new MimeBodyPart();
            attachmentPart.attachFile(new File("example.pdf"));
            multipart.addBodyPart(attachmentPart);

            message.setContent(multipart);

            // 6. Send
            Transport.send(message);
            System.out.println("Email sent successfully!");
        } catch (MessagingException e) {
            e.printStackTrace();
        }
    }
}

Visual: Email MIME Structure


Common Exceptions

Exception Cause Solution
AuthenticationFailedException Wrong username/password or 2FA blocked Use an app-specific password (Gmail).
SocketException SMTP server unreachable Check firewall/VPN or server status.
MessagingException Invalid email format Validate recipients with InternetAddress.validate().

2. File Handling in Java: Reading, Writing, and Parsing

Java provides multiple ways to handle files:

  • Legacy I/O: File, FileReader, FileWriter (simpler but less flexible).
  • NIO.2 (New I/O): Path, Files, BufferedReader (recommended for modern code).
AppleElephantTWO.TXT
Output file after regex filtering (vowel-starting words)
Line 1: Hello worldLine 2: Apple banana orangeLine 3: ElephantONE.TXT
Input file structure before vowel-word filtering

Key Classes

classDiagram
    class Path {
        +InputStream newInputStream()
        +OutputStream newOutputStream()
        +List~String~ readAllLines()
    }
    class Files {
        +static Path of(String)
        +static void write(Path, CharSequence, Charset)
        +static void copy(Path, Path, CopyOption...)
    }
    class BufferedReader {
        +String readLine()
        +void close()
    }
    Path --> Files : static methods
    Path --> BufferedReader : creates

Example 1: Copying Words Starting with Vowels (Exam Question)

Task: Copy words starting with vowels from ONE.TXT to TWO.TXT.

import java.nio.file.*;
import java.util.regex.*;

public class VowelWordCopier {
    public static void main(String[] args) throws Exception {
        Path input = Paths.get("ONE.TXT");
        Path output = Paths.get("TWO.TXT");

        // Read all lines and filter words starting with vowels
        String content = Files.readString(input);
        Pattern vowelPattern = Pattern.compile("\\b[AEIOUaeiou]\\w*\\b");
        Matcher matcher = vowelPattern.matcher(content);

        // Write matches to output file
        Files.write(output, matcher.results().map(MatchResult::group).toList());
    }
}

Visual: File Processing Steps


1. Open input file (ONE.TXT) → 2. Read content → 3. Apply regex filter → 4. Write matches to output file (TWO.TXT).

Example 2: Parsing a CSV File (Real-World Use)

Scenario: NEPSE stock data is stored in stocks.csv with columns: Symbol,Price,Change.

import java.nio.file.*;
import java.util.*;

public class StockParser {
    public static void main(String[] args) throws Exception {
        Path csvFile = Paths.get("stocks.csv");
        List<String> lines = Files.readAllLines(csvFile);

        // Skip header and parse each line
        for (int i = 1; i < lines.size(); i++) {
            String[] data = lines.get(i).split(",");
            String symbol = data[0];
            double price = Double.parseDouble(data[1]);
            double change = Double.parseDouble(data[2]);

            System.out.printf("%s: %.2f (Change: %.2f%%)\n", symbol, price, change);
        }
    }
}

Visual: CSV Parsing Example


Common File Operations

Operation Legacy I/O NIO.2 (Recommended)
Read entire file Files.readAllBytes() Files.readString()
Write to file FileWriter Files.write()
Line-by-line reading BufferedReader Files.lines() → Stream
Directory listing File.listFiles() Files.list()
File locking Not supported FileLock (NIO.2)

## In the Real World

  1. eSewa/Khalti Payment Notifications

    • Idea Used: Java Mail API sends automated email receipts to users after transactions.
    • How: After a payment, the system constructs a Message with transaction details (amount, timestamp) and sends it via SMTP. Attachments (e.g., PDF receipts) use MimeBodyPart.
  2. Daraz Order Processing

    • Idea Used: File handling parses order logs (CSV/JSON) to generate reports.
    • How: A BufferedReader reads orders_2023.csv, filters completed orders, and writes summaries to sales_report.txt using Files.write().
  3. NTC Network Log Analysis

    • Idea Used: Regex in file handling extracts error patterns from log files.
    • How: Pattern.compile("ERROR: \\d+") scans ntc_logs.txt to count network failures, written to error_summary.log.
  4. Bank Loan Interest Calculations (Global Bank)

    • Idea Used: File I/O reads customer data (CSV) and calculates interest using Scanner.
    • Worked Example:
      • Input (customers.csv):
        ID,Principal,Rate,Time
        1,10000,5,2
        2,20000,6,1
        
      • Code:
        double interest = (principal * rate * time) / 100;
        Files.write(Path.of("interest.txt"), String.valueOf(interest).getBytes());
        
      • Output: interest.txt contains 1000 (for customer 1).

3. Advanced Topics

A. Handling Large Files with Streams

For files >10MB, use streams to avoid memory overload:

try (Stream<String> lines = Files.lines(Path.of("large_log.txt"))) {
    lines.filter(line -> line.contains("ERROR"))
         .forEach(System.out::println);
}

B. Serialization (Saving Objects to Files)

Convert Java objects to/from files using ObjectOutputStream:

// Save
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.ser"));
oos.writeObject(customerList);

// Load
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"));
List<Customer> loadedList = (List<Customer>) ois.readObject();

C. File Locking (Avoiding Concurrent Access)

try (FileLock lock = Files.lock(Path.of("config.txt"), LockOption.NONE)) {
    // Critical section: modify file
} catch (OverlappingFileLockException e) {
    System.err.println("File is locked by another process!");
}

## Exam Tip

  1. For Java Mail API Questions:

    • Always include SMTP properties (host, port, auth) and exception handling (MessagingException).
    • Use MimeMultipart for emails with attachments or mixed content.
    • Common Pitfalls:
      • Forgetting Transport.send().
      • Not enabling TLS (mail.smtp.starttls.enable).
      • Hardcoding passwords (use environment variables in production).
  2. For File Handling Questions:

    • Path vs. File: Prefer Path (NIO.2) for modern code. Example:
      Path path = Paths.get("data.txt"); // Better than File file = new File("data.txt");
      
    • Regex Tricks: Use \\b for word boundaries (e.g., \b[AEIOU]\\w*).
    • File Formats:
      • CSV: Split by , and skip headers.
      • Binary: Use Files.readAllBytes() and DataInputStream.
    • Exam Shortcuts:
      • To read a file line-by-line: Files.lines(path).forEach(System.out::println).
      • To write: Files.write(path, "content".getBytes()).
  3. Past Exam Patterns:

    • Programming Questions: Expect tasks like:
      • Filter words from a file (regex).
      • Parse CSV/JSON data.
      • Send an email with attachments.
    • Theory Questions: Focus on:
      • JavaMail architecture (Session → Message → Transport).
      • NIO.2 vs. legacy I/O (advantages of Path/Files).
      • MIME types (text/plain, multipart/mixed).
  4. Code Templates:

    • Email Sender:
      Session session = Session.getInstance(props, authenticator);
      Message message = new MimeMessage(session);
      // ... set properties ...
      Transport.send(message);
      
    • File Reader:
      try (Stream<String> lines = Files.lines(path)) {
          lines.filter(...).forEach(...);
      }
      

Visual Summary:


| Feature               | Java Mail API                          | File Handling (NIO.2)               |
|-----------------------|----------------------------------------|-------------------------------------|
| Purpose               | Send/receive emails                   | Read/write files                    |
| Key Classes           | Session, Message, Transport           | Path, Files, BufferedReader         |
| Protocols             | SMTP, IMAP, POP3                      | N/A                                 |
| Common Exceptions     | MessagingException                    | IOException, FileNotFoundException  |
| Modern Alternative    | N/A                                   | NIO.2 (Path, Files)                 |

In the real world

  • Daraz Order Confirmations: Uses JavaMail API to send automated email notifications with order details (HTML + attachments like invoices) to customers after purchase. The MimeMultipart structure ensures compatibility across email clients.
  • NTC Server Log Analysis: Java’s Files.readAllLines() and regex parsing (Pattern/Matcher) extract error patterns from log files (e.g., SocketException entries) to generate daily reports for network administrators.
  • NEPSE Stock Data Processing: CSV files from NEPSE are parsed using Scanner or Files.lines() to calculate daily price changes, which are then emailed to subscribers via JavaMail’s Transport.send().

Based on the TU BSc CSIT syllabus for Advanced Java Programming (CSC409), unit 9.

Discussion

Loading…