diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp
index 8e37b1418c14ffbfe44f76de9257a2cfc0f4154f..e4f39aac0450cdb5244776964b4dc237432ebda8 100755
--- a/indra/newview/llpanelsnapshotpostcard.cpp
+++ b/indra/newview/llpanelsnapshotpostcard.cpp
@@ -40,6 +40,7 @@
 #include "llpostcard.h"
 #include "llviewercontrol.h" // gSavedSettings
 #include "llviewerwindow.h"
+#include "llviewerregion.h"
 
 #include <boost/regex.hpp>
 
@@ -67,7 +68,8 @@ class LLPanelSnapshotPostcard
 	/*virtual*/ void updateControls(const LLSD& info);
 
 	bool missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response);
-	void sendPostcard();
+    static void sendPostcardFinished(LLSD result);
+    void sendPostcard();
 
 	void onMsgFormFocusRecieved();
 	void onFormatComboCommit(LLUICtrl* ctrl);
@@ -166,24 +168,44 @@ bool LLPanelSnapshotPostcard::missingSubjMsgAlertCallback(const LLSD& notificati
 }
 
 
-void LLPanelSnapshotPostcard::sendPostcard()
+void LLPanelSnapshotPostcard::sendPostcardFinished(LLSD result)
 {
-	std::string to(getChild<LLUICtrl>("to_form")->getValue().asString());
-	std::string subject(getChild<LLUICtrl>("subject_form")->getValue().asString());
+    LL_WARNS() << result << LL_ENDL;
 
-	LLSD postcard = LLSD::emptyMap();
-	postcard["pos-global"] = LLFloaterSnapshot::getPosTakenGlobal().getValue();
-	postcard["to"] = to;
-	postcard["from"] = mAgentEmail;
-	postcard["name"] = getChild<LLUICtrl>("name_form")->getValue().asString();
-	postcard["subject"] = subject;
-	postcard["msg"] = getChild<LLUICtrl>("msg_form")->getValue().asString();
-	LLPostCard::send(LLFloaterSnapshot::getImageData(), postcard);
+    std::string state = result["state"].asString();
 
-	// Give user feedback of the event.
-	gViewerWindow->playSnapshotAnimAndSound();
+    LLPostCard::reportPostResult((state == "complete"));
+}
 
-	LLFloaterSnapshot::postSave();
+
+void LLPanelSnapshotPostcard::sendPostcard()
+{
+    // upload the image
+    std::string url = gAgent.getRegion()->getCapability("SendPostcard");
+    if (!url.empty())
+    {
+        LLResourceUploadInfo::ptr_t uploadInfo(new LLPostcardUploadInfo(
+            mAgentEmail,
+            getChild<LLUICtrl>("name_form")->getValue().asString(),
+            getChild<LLUICtrl>("to_form")->getValue().asString(),
+            getChild<LLUICtrl>("subject_form")->getValue().asString(),
+            getChild<LLUICtrl>("msg_form")->getValue().asString(),
+            LLFloaterSnapshot::getPosTakenGlobal(),
+            LLFloaterSnapshot::getImageData(),
+            boost::bind(&LLPanelSnapshotPostcard::sendPostcardFinished, _4)));
+
+        LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
+    }
+    else
+    {
+        LL_WARNS() << "Postcards unavailable in this region." << LL_ENDL;
+    }
+
+
+    // Give user feedback of the event.
+    gViewerWindow->playSnapshotAnimAndSound();
+
+    LLFloaterSnapshot::postSave();
 }
 
 void LLPanelSnapshotPostcard::onMsgFormFocusRecieved()
diff --git a/indra/newview/llpostcard.cpp b/indra/newview/llpostcard.cpp
index 5987044bffe2191a7ebc72d3a53daf14c890cda4..4e34ec912eb0640d3f3c8a47050f0e8d34d233e7 100755
--- a/indra/newview/llpostcard.cpp
+++ b/indra/newview/llpostcard.cpp
@@ -37,121 +37,42 @@
 #include "llagent.h"
 #include "llassetstorage.h"
 #include "llassetuploadresponders.h"
+#include "llviewerassetupload.h"
 
 ///////////////////////////////////////////////////////////////////////////////
-// misc
 
-static void postcard_upload_callback(const LLUUID& asset_id, void *user_data, S32 result, LLExtStat ext_status)
+LLPostcardUploadInfo::LLPostcardUploadInfo(std::string emailFrom, std::string nameFrom, std::string emailTo,
+        std::string subject, std::string message, LLVector3d globalPosition,
+        LLPointer<LLImageFormatted> image, invnUploadFinish_f finish) :
+    LLBufferedAssetUploadInfo(LLUUID::null, image, finish),
+    mEmailFrom(emailFrom),
+    mNameFrom(nameFrom),
+    mEmailTo(emailTo),
+    mSubject(subject),
+    mMessage(message),
+    mGlobalPosition(globalPosition)
 {
-	LLSD* postcard_data = (LLSD*)user_data;
-
-	if (result)
-	{
-		// TODO: display the error messages in UI
-		LL_WARNS() << "Failed to send postcard: " << LLAssetStorage::getErrorString(result) << LL_ENDL;
-		LLPostCard::reportPostResult(false);
-	}
-	else
-	{
-		// only create the postcard once the upload succeeds
-
-		// request the postcard
-		const LLSD& data = *postcard_data;
-		LLMessageSystem* msg = gMessageSystem;
-		msg->newMessage("SendPostcard");
-		msg->nextBlock("AgentData");
-		msg->addUUID("AgentID",			gAgent.getID());
-		msg->addUUID("SessionID",		gAgent.getSessionID());
-		msg->addUUID("AssetID",			data["asset-id"].asUUID());
-		msg->addVector3d("PosGlobal",	LLVector3d(data["pos-global"]));
-		msg->addString("To",			data["to"]);
-		msg->addString("From",			data["from"]);
-		msg->addString("Name",			data["name"]);
-		msg->addString("Subject",		data["subject"]);
-		msg->addString("Msg",			data["msg"]);
-		msg->addBOOL("AllowPublish",	FALSE);
-		msg->addBOOL("MaturePublish",	FALSE);
-		gAgent.sendReliableMessage();
-
-		LLPostCard::reportPostResult(true);
-	}
-
-	delete postcard_data;
 }
 
-
-///////////////////////////////////////////////////////////////////////////////
-// LLPostcardSendResponder
-
-class LLPostcardSendResponder : public LLAssetUploadResponder
+LLSD LLPostcardUploadInfo::generatePostBody()
 {
-	LOG_CLASS(LLPostcardSendResponder);
-
-public:
-	LLPostcardSendResponder(const LLSD &post_data,
-							const LLUUID& vfile_id,
-							LLAssetType::EType asset_type):
-	    LLAssetUploadResponder(post_data, vfile_id, asset_type)
-	{
-	}
-
-	/*virtual*/ void httpFailure()
-	{
-		LL_WARNS() << "Sending postcard failed, status: " << getStatus() << LL_ENDL;
-		LLPostCard::reportPostResult(false);
-	}
-
-	/*virtual*/ void uploadComplete(const LLSD& content)
-	{
-		LL_INFOS() << "Postcard sent" << LL_ENDL;
-		LL_DEBUGS("Snapshots") << "content: " << content << LL_ENDL;
-		LLPostCard::reportPostResult(true);
-	}
+    LLSD postcard = LLSD::emptyMap();
+    postcard["pos-global"] = mGlobalPosition.getValue();
+    postcard["to"] = mEmailTo;
+    postcard["from"] = mEmailFrom;
+    postcard["name"] = mNameFrom;
+    postcard["subject"] = mSubject;
+    postcard["msg"] = mMessage;
+
+    return postcard;
+}
 
-	/*virtual*/ void uploadFailure(const LLSD& content)
-	{
-		LL_WARNS() << "Sending postcard failed: " << content << LL_ENDL;
-		LLPostCard::reportPostResult(false);
-	}
-};
 
 ///////////////////////////////////////////////////////////////////////////////
 // LLPostCard
 
 LLPostCard::result_callback_t LLPostCard::mResultCallback;
 
-// static
-void LLPostCard::send(LLPointer<LLImageFormatted> image, const LLSD& postcard_data)
-{
-	LLTransactionID transaction_id;
-	LLAssetID asset_id;
-
-	transaction_id.generate();
-	asset_id = transaction_id.makeAssetID(gAgent.getSecureSessionID());
-	LLVFile::writeFile(image->getData(), image->getDataSize(), gVFS, asset_id, LLAssetType::AT_IMAGE_JPEG);
-
-	// upload the image
-	std::string url = gAgent.getRegion()->getCapability("SendPostcard");
-	if (!url.empty())
-	{
-		LL_INFOS() << "Sending postcard via capability" << LL_ENDL;
-		// the capability already encodes: agent ID, region ID
-		LL_DEBUGS("Snapshots") << "url: " << url << LL_ENDL;
-		LL_DEBUGS("Snapshots") << "body: " << postcard_data << LL_ENDL;
-		LL_DEBUGS("Snapshots") << "data size: " << image->getDataSize() << LL_ENDL;
-		LLHTTPClient::post(url, postcard_data,
-			new LLPostcardSendResponder(postcard_data, asset_id, LLAssetType::AT_IMAGE_JPEG));
-	}
-	else
-	{
-		LL_INFOS() << "Sending postcard" << LL_ENDL;
-		LLSD* data = new LLSD(postcard_data);
-		(*data)["asset-id"] = asset_id;
-		gAssetStorage->storeAssetData(transaction_id, LLAssetType::AT_IMAGE_JPEG,
-			&postcard_upload_callback, (void *)data, FALSE);
-	}
-}
-
 // static
 void LLPostCard::reportPostResult(bool ok)
 {
diff --git a/indra/newview/llpostcard.h b/indra/newview/llpostcard.h
index 0eb118b90625e757468f7162d79f4767dd9a7190..24157be636ddb3ed6d0ff5234a0a387cee15e1f8 100755
--- a/indra/newview/llpostcard.h
+++ b/indra/newview/llpostcard.h
@@ -29,7 +29,12 @@
 
 #include "llimage.h"
 #include "lluuid.h"
+#include "llviewerassetupload.h"
 
+/// *TODO$: this LLPostCard class is a hold over and should be removed.  Right now
+/// all it does is hold a pointer to a call back function which is invoked by 
+/// llpanelsnapshotpostcard's finish function. (and all that call back does is 
+/// set the status in the floater.
 class LLPostCard
 {
 	LOG_CLASS(LLPostCard);
@@ -37,7 +42,6 @@ class LLPostCard
 public:
 	typedef boost::function<void(bool ok)> result_callback_t;
 
-	static void send(LLPointer<LLImageFormatted> image, const LLSD& postcard_data);
 	static void setPostResultCallback(result_callback_t cb) { mResultCallback = cb; }
 	static void reportPostResult(bool ok);
 
@@ -45,4 +49,24 @@ class LLPostCard
 	static result_callback_t mResultCallback;
 };
 
+
+class LLPostcardUploadInfo : public LLBufferedAssetUploadInfo
+{
+public:
+    LLPostcardUploadInfo(std::string emailFrom, std::string nameFrom, std::string emailTo,
+        std::string subject, std::string message, LLVector3d globalPosition,
+        LLPointer<LLImageFormatted> image, invnUploadFinish_f finish);
+
+    virtual LLSD generatePostBody();
+private:
+    std::string mEmailFrom;
+    std::string mNameFrom;
+    std::string mEmailTo;
+    std::string mSubject;
+    std::string mMessage;
+    LLVector3d mGlobalPosition;
+
+};
+
+
 #endif // LL_LLPOSTCARD_H
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index 51374922e8806b6800f22b264fd73d80b676e01d..b00f99cf5cb0c6f071dfe0934bc4fc1954f28724 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -458,6 +458,40 @@ LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType:
     
 }
 
+LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LLImageFormatted> image, invnUploadFinish_f finish) :
+    LLResourceUploadInfo(std::string(), std::string(), 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
+        0, 0, 0, 0),
+    mTaskUpload(false),
+    mTaskId(LLUUID::null),
+    mContents(),
+    mInvnFinishFn(finish),
+    mTaskFinishFn(NULL),
+    mStoredToVFS(false)
+{
+    setItemId(itemId);
+
+    EImageCodec codec = static_cast<EImageCodec>(image->getCodec());
+
+    switch (codec)
+    {
+    case IMG_CODEC_JPEG:
+        setAssetType(LLAssetType::AT_IMAGE_JPEG);
+        LL_INFOS() << "Upload Asset type set to JPEG." << LL_ENDL;
+        break;
+    case IMG_CODEC_TGA:
+        setAssetType(LLAssetType::AT_IMAGE_TGA);
+        LL_INFOS() << "Upload Asset type set to TGA." << LL_ENDL;
+        break;
+    default:
+        LL_WARNS() << "Unknown codec to asset type transition. Codec=" << (int)codec << "." << LL_ENDL;
+        break;
+    }
+
+    size_t imageSize = image->getDataSize();
+    mContents.reserve(imageSize);
+    mContents.assign((char *)image->getData(), imageSize);
+}
+
 LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID taskId, LLUUID itemId, LLAssetType::EType assetType, std::string buffer, taskUploadFinish_f finish) :
     LLResourceUploadInfo(std::string(), std::string(), 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
         0, 0, 0, 0),
@@ -526,24 +560,30 @@ LLUUID LLBufferedAssetUploadInfo::finishUpload(LLSD &result)
     }
     else
     {
-        LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(itemId);
-        if(!item)
+        LLUUID newItemId(LLUUID::null);
+
+        if (itemId.notNull())
         {
-            LL_WARNS() << "Inventory item for " << getDisplayName() << " is no longer in agent inventory." << LL_ENDL;
-            return newAssetId;
-        }
+            LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(itemId);
+            if (!item)
+            {
+                LL_WARNS() << "Inventory item for " << getDisplayName() << " is no longer in agent inventory." << LL_ENDL;
+                return newAssetId;
+            }
 
-        // Update viewer inventory item
-        LLPointer<LLViewerInventoryItem> newItem = new LLViewerInventoryItem(item);
-        newItem->setAssetUUID(newAssetId);
+            // Update viewer inventory item
+            LLPointer<LLViewerInventoryItem> newItem = new LLViewerInventoryItem(item);
+            newItem->setAssetUUID(newAssetId);
 
-        gInventory.updateItem(newItem);
+            gInventory.updateItem(newItem);
 
-        LL_INFOS() << "Inventory item " << item->getName() << " saved into " << newAssetId.asString() << LL_ENDL;
+            newItemId = newItem->getUUID();
+            LL_INFOS() << "Inventory item " << item->getName() << " saved into " << newAssetId.asString() << LL_ENDL;
+        }
 
         if (mInvnFinishFn)
         {
-            mInvnFinishFn(itemId, newAssetId, newItem->getUUID(), result);
+            mInvnFinishFn(itemId, newAssetId, newItemId, result);
         }
         gInventory.notifyObservers();
     }
diff --git a/indra/newview/llviewerassetupload.h b/indra/newview/llviewerassetupload.h
index 604db808b12faed6d2ac3a8d9323833a2b7e7bf1..6e036fe52638f1b69b2445151b2115bc7245f8ab 100644
--- a/indra/newview/llviewerassetupload.h
+++ b/indra/newview/llviewerassetupload.h
@@ -34,6 +34,7 @@
 #include "lleventcoro.h"
 #include "llcoros.h"
 #include "llcorehttputil.h"
+#include "llimage.h"
 
 //=========================================================================
 class LLResourceUploadInfo
@@ -162,6 +163,7 @@ class LLBufferedAssetUploadInfo : public LLResourceUploadInfo
     typedef boost::function<void(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response)> taskUploadFinish_f;
 
     LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType::EType assetType, std::string buffer, invnUploadFinish_f finish);
+    LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LLImageFormatted> image, invnUploadFinish_f finish);
     LLBufferedAssetUploadInfo(LLUUID taskId, LLUUID itemId, LLAssetType::EType assetType, std::string buffer, taskUploadFinish_f finish);
 
     virtual LLSD        prepareUpload();