Tuesday, February 27, 2018

SharePoint 2013 REST Send Email and Limitations

In order to send email from SharePoint Hosted App using REST, use the below code snippet.

var sendEmail = function (from, to, cc1, cc2, body, subject) {             
                var baseUrl = _spPageContextInfo.webServerRelativeUrl;
                var urlTemplate = baseUrl + "/_api/SP.Utilities.Utility.SendEmail";
                return getFormDigest().then(function (digest) {
                    $.ajax({
                        contentType: 'application/json',
                        url: urlTemplate,
                        type: "POST",
                        data: JSON.stringify({
                            'properties': {
                                '__metadata': { 'type': 'SP.Utilities.EmailProperties' },
                                'From': from,
                                'To': { 'results': [to, cc1, cc2] },
                                'Body': body,
                                'Subject': subject
                            }
                        }
                      ),
                        headers: {
                            "Accept": "application/json;odata=verbose",
                            "content-type": "application/json;odata=verbose",
                            "X-RequestDigest": $("#__REQUESTDIGEST").val()
                         
                        },
                        success: function (data) {
                            console.log("An email was sent.");
                        },
                        error: function (args) {
                            console.log("We had a problem and an email was not sent.");
                        }
                    });
                });
            };

However there are some limitations:

1. The To user must be a valid SharePoint user, cannot be a external user. For security reasons, it doesn't allow sending email to external users.

2. The user who is logging and executing this code should have manage web permissions.

SharePoint PowerShell Get InActive Sites Report

I am asked to generate a site report to identify which all site collections/ sites / sub sites are not in use for so long, so that they can be archived.

I choose to write a PowerShell script to visit all the site collections, sites, sub sites and generate a CSV report with below information. Based on the last accessed/modified date, decision making happens whether to archive/delete the site.


Site Title
Site URL
Site Users Count
Site Last Modified
Web Last Modified (item content in a web)
List Title (lists under a web)
List Items Count

Below is the PowerShell script to generate the site report.

$timestamp = get-date -format "yyyyMMdd_hhmmtt"
$filenameStart = "MSHSSiteReport"
$logfile = ("D:\{0}{1}.csv" -f $filenamestart, $timestamp)

$header = "webname,weburl,usercount,sitelastmodified,weblastmodified,archive,listname,itemcount"
$header | out-file -FilePath $logfile

$result = @()

# Get All Web Applications
$WebApps=Get-SPWebApplication
foreach($webApp in $WebApps)
{
    if(!$webApp.Url.StartsWith("https://workspace.mountsinai.org/"))
    {
        continue
    }
    Write-Host $webApp.Url -ForegroundColor Red
    foreach ($SPsite in $webApp.Sites)
    {   
        Write-Host $SPsite.Url -BackgroundColor DarkCyan
       # get the collection of webs
       foreach($SPweb in $SPsite.AllWebs)
        {
            if($SPsite.Url -eq $SPweb.Url)
            { 
                $SizeInKB = $SPsite.Usage.Storage
                $SizeInGB = $SizeInKB/1024/1024 #/1024
                $SizeInGB = [math]::Round($SizeInGB,2)
                Write-Host $SizeInGB MB -ForegroundColor Yellow
            }

            $siteTitle = $SPweb.title
            $siteUrl = $spweb.URL
            $userCount = $SPweb.Users.Count
            $siteLastModified = $SPsite.LastContentModifiedDate
            $webLastModified = $SPweb.LastItemModifiedDate
                                   
            $archive = "False"
            if($SPweb.LastItemModifiedDate -lt ((Get-Date).AddMonths(-12)))
            {
                $archive = "True"  
            }

            write-host $siteTitle ":" $siteUrl ":" $userCount ":" $webLastModified ":" $archive

            $report = New-Object System.Object
         $report | Add-Member -MemberType NoteProperty -Name "Title" -Value $siteTitle
         $report | Add-Member -MemberType NoteProperty -Name "URL" -Value $siteUrl
         $report | Add-Member -MemberType NoteProperty -Name "UserCount" -Value $userCount
         $report | Add-Member -MemberType NoteProperty -Name "SiteLastModified" -Value $siteLastModified
         $report | Add-Member -MemberType NoteProperty -Name "WebLastModified" -Value $webLastModified
         $report  | Add-Member -MemberType NoteProperty -Name "Archive" -Value $archive
         $report | Add-Member -MemberType NoteProperty -Name "List" -Value ""
         $report | Add-Member -MemberType NoteProperty -Name "ItemCount" -Value ""

         $result += $report

      Write-Host ([String]::Format("Procesing web {0}",$SPweb.Url)) -foregroundcolor Yellow
      foreach($l in $SPweb.Lists)
      {
               
           Write-Host ([String]::Format("List, '{0}', has {1} items.",$l.Title, $l.ItemCount)) -foregroundcolor Green
               
                    $report = New-Object System.Object
                 $report | Add-Member -MemberType NoteProperty -Name "Title" -Value ""
                 $report | Add-Member -MemberType NoteProperty -Name "URL" -Value ""
                 $report | Add-Member -MemberType NoteProperty -Name "UserCount" -Value ""
                 $report | Add-Member -MemberType NoteProperty -Name "SiteLastModified" -Value ""
                 $report | Add-Member -MemberType NoteProperty -Name "WebLastModified" -Value ""
                 $report | Add-Member -MemberType NoteProperty -Name "Archive" -Value $archive
                 $report | Add-Member -MemberType NoteProperty -Name "List" -Value $l.Title
                 $report | Add-Member -MemberType NoteProperty -Name "ItemCount" -Value $l.ItemCount

                 $result += $report
              
      } 

        }
    }
  }
 

$result | Export-Csv -NoTypeInformation -Path $logfile


Monday, February 19, 2018

Microsoft Azure WebJobs


WebJobs in Microsoft Azure is considered to be a feature of Azure App Service. It lets you run a program or script in the same context as a web app, API app or mobile app. Azure WebJobs is a feature provided by the cloud computing platform of Microsoft which enables you to run programs/scripts as background processes by a part of Azure websites. You can upload and run an executable file such as as cmd, bat, exe (.NET), ps1, sh, php, py, js and jar. These programs run as WebJobs on a schedule (cron) or continuously.

Here are some typical scenarios that would be great for the Windows Azure WebJobs SDK:

ü  Image processing or other CPU-intensive work.
ü  Queue processing.
ü  RSS aggregation.
ü  File maintenance, such as aggregating or cleaning up log files.
ü  Other long-running tasks that you want to run in a background thread, such as sending emails.

WebJobs are invoked in two different ways, either they are triggered or they are continuously running. Triggered jobs happen on a schedule or when some event happens and Continuous jobs basically run a while loop.
WebJobs are deployed by copying them to the right place in the file-system (or using a designated API which will do the same). 

The following file types are accepted as runnable scripts that can be used as a job:

ü  .exe - .NET assemblies compiled with the WebJobs SDK
ü  .cmd, .bat, .exe (using windows cmd)
ü  .sh (using bash)
ü  .php (using php)
ü  .py (using python)
ü  .js (using node)

After you deploy your WebJobs from the portal, you can start and stop jobs, delete them, upload jobs as ZIP files, etc. You've got full control.

A good thing to point out, though, is that Azure WebJobs are more than just scheduled scripts, you can also create WebJobs as .NET projects written in C# or whatever.

WebJobs best work with Azure Queues, Blobs, Tables and Service Bus. WebJobs SDK has built in API to listen for the incoming data into these storage systems, hence the Job will be triggered when there is a new data and process it accordingly.

Thursday, February 15, 2018

How to View SharePoint App Web Site Contents

I know most of the SharePoint App developers or users would definitely look for site contents of an App Web and List Settings in an App Web. But it turns out that there is no direct way to access the App Web Contents similar to a regular site's Site Contents.

However I have a trick to see the app web site contents by typing in the below URL as a suffix to your app web URL.
/_layouts/15/mcontent.aspx

Example: http://app-web-url/_layouts/15/mcontent.aspx

It lists all the available lists/libraries in the app web. But you will notice that the way the contents are listed is different from the regular Site Contents and by clicking on the list/library will redirects to list/library settings instead actual list. On the settings page you see the List Name which redirects to the actual list content.

Hope this post is helpful...

Monday, February 12, 2018

JQuery body append html


I wanted to append the html to body like below and the html control will be accessed in a JavaScript function.

$("body").append('<div id="vedioControl">VEDIO CONTROL</div >');

When I accessed the html control in a JavaScript function, I got an operation aborted error.
I have double checked the above statement, nothing is wrong.

Later I found that that, html will not be added to body unless the DOM is loaded.
To make sure the DOM is loaded, added the statement within the .ready function.

$(document).ready(function()
{     
      $("body").append('<div id=" vedioControl "> VEDIO CONTROL</div>');
});