public function save(
        $attach_dir,
        $filenameStrategy = Parser::ATTACHMENT_DUPLICATE_SUFFIX
    ) {
        $attach_dir = rtrim($attach_dir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
        if (!is_dir($attach_dir)) {
            mkdir($attach_dir);
        }

        // Determine filename
        switch ($filenameStrategy) {
            case Parser::ATTACHMENT_RANDOM_FILENAME:
                $attachment_path = tempnam($attach_dir, '');
                break;
            case Parser::ATTACHMENT_DUPLICATE_THROW:
            case Parser::ATTACHMENT_DUPLICATE_SUFFIX:
                $attachment_path = $attach_dir.$this->getFilename();
                break;
            default:
                throw new Exception('Invalid filename strategy argument provided.');
        }

        // Handle duplicate filename
        if (file_exists($attachment_path)) {
            switch ($filenameStrategy) {
                case Parser::ATTACHMENT_DUPLICATE_THROW:
                    throw new Exception('Could not create file for attachment: duplicate filename.');
                case Parser::ATTACHMENT_DUPLICATE_SUFFIX:
                    $attachment_path = $this->suffixFileName($attachment_path);
                    break;
            }
        }

        /** @var resource $fp */
        if ($fp = fopen($attachment_path, 'w')) {
            while ($bytes = $this->read()) {
                fwrite($fp, $bytes);
            }
            fclose($fp);
            return realpath($attachment_path);
        } else {
            throw new Exception('Could not write attachments. Your directory may be unwritable by PHP.');
        }
    }